.net 4.0 为什么可以';分配列表<;int>;到IEnumerable<;对象>;在.NET4.0中

.net 4.0 为什么可以';分配列表<;int>;到IEnumerable<;对象>;在.NET4.0中,.net-4.0,ienumerable,covariance,value-type,.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 }; IEnumerable id=new List(){“0001”、“0002”、“0003”}; 它工作得很好 但当我尝试这样做时: IEnumera

我尝试这样做:

IEnumerable<object> ids = new List<string>() { "0001", "0002", "0003" };
IEnumerable<object> intIds = new List<System.Int32>() { 1, 2, 3 };
IEnumerable id=new List(){“0001”、“0002”、“0003”};
它工作得很好

但当我尝试这样做时:

IEnumerable<object> ids = new List<string>() { "0001", "0002", "0003" };
IEnumerable<object> intIds = new List<System.Int32>() { 1, 2, 3 };
IEnumerable intIds=new List(){1,2,3};
Visual Studio告诉我: 无法将类型“System.Collections.Generic.List”隐式转换为“System.Collections.Generic.IEnumerable”。存在显式转换(是否缺少强制转换?)


这是为什么?

int
是一种值类型,只能装箱到
对象
——它不从
对象
继承。由于您使用的是
IEnumerable
,因此应该可以:

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

简单地说:.NET4中的泛型差异不支持值类型的类型参数的差异

它可以用于引用类型的原因是,一旦CLR确定它知道泛型转换是安全的,它就可以以相同的方式处理所有引用值——它们在内部具有相同的表示形式。将
字符串
引用转换为
对象
引用不需要实际转换,反之亦然,如果您知道它肯定是对字符串的引用-基本上是相同的位。因此,生成的本机代码可以将引用视为引用,高兴的是,关于方差的规则保证了在类型安全级别不会发生任何不愉快的事情,并且不会对值本身执行任何转换

对于值类型,或者对于转换不是“引用转换”(即保留一个表示)的引用类型,情况并非如此。这就是为什么不能编写
IEnumerable names=new List()顺便说一下…

来自:

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

// int is a value type, so the code doesn't compile.
IEnumerable<Object> objects = new List<int>(); // Compiler error here.
//int是一种值类型,因此代码不会编译。
IEnumerable objects=新列表();//这里有编译器错误。

另一个解决方案是使用扩展方法Enumerable.Cast,如下所示:

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

MethodThatTakesIEnumerableOfObject(a.Cast(Of Object))

真的!谢谢你的快速回复。这节省了我一些努力。为什么这是公认的答案?这完全是假的!Jon的回答中给出了真正的原因。很好,它们的继承与引用类型从对象继承的意义不同。当一个值类型被“强制转换”到一个对象时,它被包装在一个对象中并存储在托管堆上。(框中)您所说的“与引用类型的含义不同”是什么意思?唯一的区别是,当您编写类
T
时,层次结构是
Object->T
,而对于结构
T
,层次结构是
Object->ValueType->T
。直接继承并没有“更好”或有太多不同。它更像是
Object-->新对象(t)-->t