为什么不能返回List <t>的方法实现一个返回IEnumerable <t>的方法?</t> </t>

时间:2014-06-13 18:32:23

标签: c# .net interface

我有一个具体的类,实现了一个带方法签名的接口

IEnumerable<T> Foo()

List<T> Foo()

编译器说List<T> Foo无法实现IEnumerable<T> Foo。为什么呢?

3 个答案:

答案 0 :(得分:2)

为什么编译器会拒绝这个?

因为规范不允许这样做:

  

出于接口映射的目的,类成员A在以下情况下匹配接口成员B:

     
      
  • A和B是方法,A和B的名称,类型和形式参数列表是相同的。

  •   
  • [...]

  •   

(引自C#5.0规范 - 13.4.4接口映射)

如果要将此功能添加到规范中,是否存在任何技术障碍?

我不知道:

  • 由于两种类型都是引用类型,因此它们保留了表示形式。因此,这些签名之间存在二进制兼容性。
  • 返回类型的协方差是类型安全的,因为返回List<T>的方法返回接口调用者所期望的IEnumerable<T>

C#和.NET中是否已有相似的功能?

是。 .NET 4支持:

  • 委托返回类型的协方差:Func<List<T>>Func<IEnumerable<T>>
  • 界面协方差:IEnumerable<List<T>>IEnumerable<IEnumerable<T>

这为该特征的可行性提供了进一步的证据。

为什么不支持呢?

只有C#团队的成员才能回答这个问题。

但是在没有进一步证据的情况下我们可以假设:

每个功能都需要指定,实施测试和维护的成本。所以开发人员只能实现一些功能。他们会选择能够为小工作带来巨大收益的功能。因此可能有更高优先级的功能,并且它不值得花时间。

有解决方法吗?

只需使用显式接口实现:

class FooClass<T> : IFoo
{
    public List<T> Foo()
    {
         //do something
    }

    IEnumerable<T> IFoo.Foo()
    {
        return Foo();
    }
}

答案 1 :(得分:1)

因为您无法更改在C#中实施的方法的签名中的返回类型或任何其他类型。

C#的语言规范是这样说的。为什么他们做出这个决定是未知的,但作为一个疯狂的猜测,他们可能认为潜在的收益不值得花费。

但是,您可以将签名保留为IEnumerable<T>,只需返回List<T>

答案 2 :(得分:0)

我无法回答为什么这样的问题,但值得注意的是,这种限制对实际影响很小,因为显式接口实现允许您使用少量胶水代码获得所需的效果:

public interface IFooable<T>
{
    IEnumerable<T> Foo();
}

public sealed class Fooable<T> : IFooable<T>
{
    public List<T> Foo()
    {
        //...
    }

    IEnumerable<T> IFooable<T>.Foo()
    {
        return Foo();
    }
}