C#编译器无法识别一个类实现了一个接口

13

下面的代码无法编译(使用VS2010),我不知道原因。编译器应该能够推断出List<TestClass>IEnumerable<ITest>是“兼容”的(对不起,没有更好的词语),但不知何故它没有。我在这里漏掉了什么?


interface ITest {
    void Test();
}


class TestClass : ITest {
    public void Test() {
    }
}

class Program {
    static void Test(IEnumerable<ITest> tests) {
        foreach(var t in tests) {
            Console.WriteLine(t);
        }
    }
    static void Main(string[] args) {
        var lst = new List<TestClass>();

        Test(lst); // fails, why?

        Test(lst.Select(t=>t as ITest)); //success

        Test(lst.ToArray()); // success
    }
}

编译器报了两个错误:

  1. 'ConsoleApplication1.Program.Test(System.Collections.Generic.IEnumerable<ConsoleApplication2.ITest>)' 的最佳重载方法存在一些无效的参数

  2. 参数 1:无法将类型为 'System.Collections.Generic.List<ConsoleApplication2.TestClass>' 的对象隐式转换为类型 'System.Collections.Generic.IEnumerable<ConsoleApplication2.ITest>'

3个回答

8
你尝试做的是covariance - 从较窄的类型(TestClass)转换为较宽的类型(ITest)。这是你经常用到的东西,例如从float转换到double时会发生。不幸的是,.Net 3.5及以下版本不支持泛型类中的协变。
.Net 4.0现在支持泛型中的协变(和逆变),只要这些泛型类使用out关键字编译为协变类型和in关键字编译为逆变类型。在.Net 4.0中,IEnumerable被定义为协变。如果你右键单击IEnumerable类型并点击“转到定义”,你会看到这个:
public interface IEnumerable<out T> : IEnumerable

如果您使用的是VS2010,则需要确保您的项目针对.NET 4.0。这可以从项目属性中更改。右键单击项目,选择属性,转到“应用程序”选项卡,并检查“目标框架”是否为.Net 4。

MSDN有更多信息


2

这与方差有关(协变和逆变);请查看此帖子以及Jon Skeet的回答。


1

检查您的项目所需的框架目标版本。此代码仅适用于 .NET 4。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接