【问题标题】:C# compiler fails to recognize a class is implementing an interfaceC# 编译器无法识别一个类正在实现一个接口
【发布时间】:2010-05-20 08:50:01
【问题描述】:

以下代码无法编译(使用 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)' 的最佳重载方法匹配有一些无效参数

  2. 参数 1:无法从 'System.Collections.Generic.List' 转换为 'System.Collections.Generic.IEnumerable'

【问题讨论】:

    标签: c# .net generics .net-4.0 covariance


    【解决方案1】:

    您正在尝试做的事情称为covariance - 从较窄的类型 (TestClass) 转换为较宽的类型 (ITest)。这是你一直习惯的东西,例如,当你从浮点数转换为双精度数时会发生这种情况。

    很遗憾,.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 has more information.

    【讨论】:

      【解决方案2】:

      这与方差(协方差和逆变)有关;看看这个post 和 Jon Skeet 的回答

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-08
          • 2012-12-15
          • 2022-01-09
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多