Why can't I assign List<int> to IEnumerable<object> in .NET 4.0

元气小坏坏 提交于 2019-12-28 20:37:32

问题


I try to do this:

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

it works great!

But when I try to do this:

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

Visual Studio tells me: Cannot implicitly convert type 'System.Collections.Generic.List' to 'System.Collections.Generic.IEnumerable'. An explicit conversion exists (are you missing a cast?)

Why is that?


回答1:


int is a value type and can only be boxed to object - it doesn't inherit from object. Since you're using an IEnumerable<object> anyway, this should work:

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



回答2:


Simply put: generic variance in .NET 4 doesn't support variance for type arguments which are value types.

The reason it can work for reference types is that once the CLR has decided it knows the generic conversion is safe, it can treat all reference values the same way - they have the same representation internally. No actual conversion is required to turn a string reference into an object reference, or vice versa if you know it's definitely a reference to a string - it's the same bits, basically. So the generated native code can just treat the references as references, happy in the knowledge that the rules around variance have guaranteed that nothing nasty will happen at the type safety level, and not performing any conversions on the values themselves.

That isn't true for value types, or for reference types where the conversion isn't a "reference conversion" (i.e. a representation-preserving one). That's why you can't write IEnumerable<XName> names = new List<string>(); by the way...




回答3:


From MSDN Blogs > C# Frequently Asked Questions > Covariance and Contravariance FAQ:

Variance is supported only if a type parameter is a reference type. Variance is not supported for value types. The following doesn’t compile either:

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



回答4:


Another solution would be to use the extension method Enumerable.Cast as such:

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

MethodThatTakesIEnumerableOfObject(a.Cast(Of Object))


来源:https://stackoverflow.com/questions/8175311/why-cant-i-assign-listint-to-ienumerableobject-in-net-4-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!