我有一些代码
public interface ISettable<TValue>
{
}
public class Control<TValue> : ISettable<TValue>
{
}
public static class ControlExtensions
{
public static TControl Set<TControl, T>(this TControl control, T value) where TControl : ISettable<T>
{
return control;
}
}
在VS2015中,Intellisense并未建议所有类型的此扩展,但在VS2017中,建议为每种类型建立此扩展名,甚至object
。
为什么在类型未实现ISettable<T>
?
答案 0 :(得分:1)
你似乎对C#中的泛型类型有点困惑。您的TValue
类型(没有任何约束)与您的扩展方法中的T
完全相同,您只需使用其他名称调用它(就像使用正式方法一样)参数)。
你方法:
public static TControl Set<TControl, T>(this TControl control, T value)
where TControl : ISettable<T>
实际上可用于任何Control<TValue>
个实例,并且T
参数将是您调用扩展方法的实例的实际TValue
类型。
那就是说,除非你有其他代码没有显示,否则这个界面本身就没什么意义:为什么你在接口本身没有Set
方法,而不是在扩展方法中?您还可以在界面controvariant的同时创建界面。像这样:
public interface ISettable<in T>
{
void Set(T value);
}
public class Control<T> : ISettable<T>
{
public void Set(T value)
{
throw new NotImplementedException();
}
}
然后,您已经在界面中声明了Set
方法,该方法将使用该界面清除devs。
编辑:为了在支持多个界面的同时拥有流畅的界面,您可以明确地声明界面方法,以便隐藏&#34;他们在调用扩展方法时(否则你无法解决那里的重载),如下所示:
public interface ISettable<in T>
{
void Set(T value);
}
public interface IClickable
{
void Click();
}
public class Control<T> : ISettable<T>, IClickable
{
void ISettable<T>.Set(T value) => throw new NotImplementedException();
void IClickable.Click() => throw new NotImplementedException();
}
public static class FluentExtensions
{
public static TControl Set<TControl, T>(this TControl source, T value)
where TControl : ISettable<T>
{
source.Set(value);
return source;
}
public static TControl Click<TControl>(this TControl source)
where TControl : IClickable
{
source.Click();
return source;
}
}
然后你就可以添加任意数量的接口,并像这样使用它们:
new Control<int>().Set(4).Click();
new Control<String>().Click().Set("It works!");