我似乎无法找到任何明确说明永远不应该做的事情,我找不到推荐的方法。所以我开始说我在这里完全错误的轨道......
我试图在接口中基于返回类型重载函数。基本上我在一个接口中有15个函数,其中9个具有相同的名称/参数但不同的返回类型,我试图将其隔离,所以我不必在界面中编写15个函数,我只想了几个.. < / p>
public interface IController
{
IEnumerable<T> Fetch<T>();
}
从这里开始我想做......
等实现 public IEnumerable<T> Fetch<T>() where T : *class*
{
return dbContext.*clas*.ToList();
}
然而我收到了编译错误......
Error 1 The constraints for type parameter 'T' of method 'Controllers.Controller.Fetch<T>()' must match the constraints for type parameter 'T' of interface method 'IController.Fetch<T>()'. Consider using an explicit interface implementation instead.
任何人对此都有任何想法...
答案 0 :(得分:2)
您无法执行此操作,因为此实现与Liskov Substitution principle冲突。
方法只能比类型层次结构中的类/接口更宽(接受更多)。
现在C#并不完全支持Liskov Substition原则(在某种意义上说,不允许扩大参数)。但这意味着,例如,如果一个方法
public class Foo {
void Bar (T parameter);
}
在第一级定义,该方法不能用
覆盖public class SubFoo : Foo {
void Bar (SubT parameter);
}
这是因为可以在Bar
级别调用SubFoo
的{{1}}方法。 Foo
级别的合同接受Foo
。因此,使类型更窄也不是一种选择。
如果一个人在类层次结构中向下移动,则会注意到:
然而,C#在接口级别支持 variance / covariance 。如果T
因此仅用于指定输出类型,则确实可以使T
更窄。这称为 variance 。您可以将其指定为:
T
这意味着public interface Foo<out T> {
T GetValue ();
}
是Foo<T>
的子类。协方差也是如此:
Foo<SuperT>
答案 1 :(得分:0)
做一些假设......如果您正在谈论EF dbContext,您实际上可以这样做:
public IEnumerable<T> Fetch<T>() where T : class
{
return dbContext.Set<T>().ToList();
}
更一般地说,你可以做这样的事情,泛型方法委托给不同类型的各种实现方法:
public IEnumerable<T> Fetch<T>() where T : class
{
if (typeof(T) == typeof(X)) return FetchX();
//Handle other types here...
}
正如Servy所指出的,要实现上述内容,您还需要修改您的接口以包含类约束(假设您需要它):
public interface IController
{
IEnumerable<T> Fetch<T>() where T: class;
}