Search code examples
c#genericsvalue-typedowncastreference-type

Passing `List` of value types to a method expecting `IEnumerable` of reference types


I am wondering why it is not possible in .NET to pass in a list of value types to a method which expects an IEnumerable of reference types. For example,

void MyMethod(IEnumerable<object> items) {}
...
var dtList = new List<DateTime> { DateTime.Now };
MyMethod(dtList); // not possible, but it's possible to make a cast object o = DateTime.Now;

As this works fine for reference types, I came to a conclusion that in the case of value types the boxing is required for each element in the collection and it might hit the performance, but I may be wrong and there are some other things to be considered.


Solution

  • Because value types are not covarient (they need to be boxed), and as such lose their identity for-which the compiler is instructed to preserve by the specs. But you can cast it .Cast<object>() (at the cost of boxing), which may or may not be an issue for you.

    For more details about identity you can see Eric Lipperts blog on Representation and identity

    All the built-in reference conversions are identity-preserving. This is why covariant and contravariant conversions of interface and delegate types require that all varying type arguments be of reference types. To ensure that a variant reference conversion is always identity-preserving, all of the conversions involving type arguments must also be identity-preserving.