基于返回类型重载接口的方法...

时间:2015-02-12 18:33:49

标签: c# interface overloading

我似乎无法找到任何明确说明永远不应该做的事情,我找不到推荐的方法。所以我开始说我在这里完全错误的轨道......

我试图在接口中基于返回类型重载函数。基本上我在一个接口中有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.   

任何人对此都有任何想法...

2 个答案:

答案 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;
}