为什么我不能将List <int>分配给.NET 4.0 </object> </int>中的IEnumerable <object>

时间:2011-11-17 22:28:30

标签: .net-4.0 ienumerable covariance value-type

我尝试这样做:

IEnumerable<object> ids = new List<string>() { "0001", "0002", "0003" };

效果很好!

但是当我尝试这样做时:

IEnumerable<object> intIds = new List<System.Int32>() { 1, 2, 3 };

Visual Studio告诉我: 无法将类型'System.Collections.Generic.List'隐式转换为'System.Collections.Generic.IEnumerable'。存在显式转换(您是否错过了演员?)

为什么?

4 个答案:

答案 0 :(得分:6)

int是一种值类型,只能装入object - 它不会从object继承。既然你正在使用IEnumerable<object>,那么这应该有效:

IEnumerable intIds = new List<int>() { 1, 2, 3 };

答案 1 :(得分:5)

简单地说:.NET 4中的泛型差异不支持作为值类型的类型参数的方差。

它可以用于引用类型的原因是,一旦CLR确定它知道通用转换是安全的,它就可以以相同的方式处理所有引用值 - 它们在内部具有相同的表示。如果您知道它绝对是对字符串的引用,则不需要实际转换将string引用转换为object引用,反之亦然 - 它基本相同,基本相同。因此,生成的本机代码可以将引用视为引用,并且知道围绕方差的规则已经保证在类型安全级别上不会发生任何讨厌,并且不对值本身执行任何转换。

对于值类型不是,对于转换不是“引用转换”(即表示保留的转换)的引用类型,。这就是你不能写IEnumerable<XName> names = new List<string>();的原因......

答案 2 :(得分:4)

来自MSDN Blogs > C# Frequently Asked Questions > Covariance and Contravariance FAQ

  

仅当类型参数是引用类型时才支持差异。值类型不支持差异。   以下内容无法编译:

// int is a value type, so the code doesn't compile.
IEnumerable<Object> objects = new List<int>(); // Compiler error here.

答案 3 :(得分:0)

另一种解决方案是使用扩展方法Enumerable.Cast:

Dim a as IEnumerable(Of Integer) = GetA()

MethodThatTakesIEnumerableOfObject(a.Cast(Of Object))