简体   繁体   English

C#编译器无法识别正在实现接口的类

[英]C# compiler fails to recognize a class is implementing an interface

The following code fails to compile (using VS2010) and I don't see why. 以下代码无法编译(使用VS2010),我不明白为什么。 The compiler should be able to infer that List<TestClass> is 'compatible' (sorry for lack of a better word) with IEnumerable<ITest> , but somehow it doesn't. 编译器应该能够推断出List<TestClass>IEnumerable<ITest>是“兼容的”(抱歉缺少一个更好的词),但不知何故它没有。 What am I missing here? 我在这里错过了什么?


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
    }
}

The compiler gives two errors: 编译器给出了两个错误:

  1. The best overloaded method match for 'ConsoleApplication1.Program.Test(System.Collections.Generic.IEnumerable<ConsoleApplication2.ITest>)' has some invalid arguments 'ConsoleApplication1.Program.Test(System.Collections.Generic.IEnumerable <ConsoleApplication2.ITest>)'的最佳重载方法匹配有一些无效的参数

  2. Argument 1: cannot convert from 'System.Collections.Generic.List<ConsoleApplication2.TestClass>' to 'System.Collections.Generic.IEnumerable<ConsoleApplication2.ITest>' 参数1:无法从'System.Collections.Generic.List <ConsoleApplication2.TestClass>'转换为'System.Collections.Generic.IEnumerable <ConsoleApplication2.ITest>'

What you are trying to do is called covariance - converting from a narrower type (TestClass) to a wider type (ITest). 你要做的是所谓的协方差 - 从较窄的类型(TestClass)转换为更宽的类型(ITest)。 It's something you'll be used to all the time, it happens when you convert from a float to a double for example. 这是你将一直习惯的东西,例如当你从一个浮点数转换为一个双精度时。

Unfortunately .Net 3.5 and lower does not support covariance in generic classes. 不幸的是.Net 3.5及更低版本不支持泛型类中的协方差。

.Net 4.0 now does support covariance (and contravariance) in generics, provided those generic classes are compiled with the keywords out for covariant types and in for contravarient types. .NET 4.0,现在不支持协方差(和逆变)仿制药,只要这些泛型类与关键字编out的协变类型和in对contravarient类型。 IEnumerable in .Net 4.0 is defined as covariant. .Net 4.0中的IEnumerable被定义为协变。 If you right click on the IEnumerable type and click "goto definition", you'll see this: 如果右键单击IEnumerable类型并单击“goto definition”,您将看到:

public interface IEnumerable<out T> : IEnumerable

If you are using VS2010, you will need to make sure your project is targeting .net 4.0. 如果您使用的是VS2010,则需要确保您的项目的目标是.net 4.0。 This can be changed from the project properties. 这可以从项目属性更改。 Right click on the project, select properties, goto the "Application" tab and check that the "Target framework" is to to .Net 4. 右键单击项目,选择属性,转到“应用程序”选项卡,然后检查“目标框架”是否为.Net 4。

MSDN has more information . MSDN有更多信息

This has to do with variance (covariance and contravariance); 这与方差(协方差和逆变)有关; check out this post and the answer by Jon Skeet 看看这篇文章和Jon Skeet的回答

Check the Target Version of the framework for your project. 检查项目框架的目标版本。 This code will only work in .NET 4 . 此代码仅适用于.NET 4。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM