以下代码无法编译(使用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
}
}
编译器给出两个错误:
最佳答案
您要尝试执行的操作称为covariance-从较窄的类型(TestClass)转换为较宽的类型(ITest)。这是您一直都会习惯的事情,例如,当您从浮点数转换为 double 数时,就会发生这种情况。
不幸的是,.Net 3.5及更低版本不支持泛型类中的协方差。
.Net 4.0现在确实支持泛型中的协方差(和逆方差),前提是这些泛型类使用协变量类型的关键字out
和协变类型的关键字in
进行编译。 .Net 4.0中的IEnumerable
定义为协变。如果右键单击IEnumerable
类型并单击“goto definition”,您将看到以下内容:
public interface IEnumerable<out T> : IEnumerable
如果您使用的是VS2010,则需要确保您的项目的目标是.net 4.0。可以从项目属性中更改。右键单击项目,选择属性,转到“应用程序”选项卡,然后检查“目标框架”是否指向.Net 4。
MSDN has more information。