Home > Net >  Why `IEnumerable<int>` is not `IEnumerable<object>`?
Why `IEnumerable<int>` is not `IEnumerable<object>`?

Time:11-29

IEnumerable<T> interface is covariant, so IEnumerable<string> is IEnumerable<object>. But why IEnumerable<int> is not IEnumerable<object> while int is object?

CodePudding user response:

Variance conversions like this are only supported if there is an implicit reference or identity conversion between the type parameters. As the spec says:

A type T<Aᵢ, ..., Aᵥ> is variance-convertible to a type T<Bᵢ, ..., Bᵥ> if T is either an interface or a delegate type declared with the variant type parameters T<Xᵢ, ..., Xᵥ>, and for each variant type parameter Xᵢ one of the following holds:

  • Xᵢ is covariant and an implicit reference or identity conversion exists from Aᵢ to Bᵢ
  • Xᵢ is contravariant and an implicit reference or identity conversion exists from Bᵢ to Aᵢ
  • Xᵢ is invariant and an identity conversion exists from Aᵢ to Bᵢ

There is neither a reference not identity conversion between int and object, only a boxing conversion.

You might be wondering what's so special about implicit reference and identity conversions, that they allow variance conversions. Well, these conversions don't require the runtime to do anything at all!

To convert from a string to object, for example, is purely a compile-time matter. Nothing needs to be done to the bits representing the string, in order to turn it into an object. After all, every string is an object.

Because of this, converting from IEnumerable<string> to IEnumerable<object> is trivial too - the runtime does not need to do anything.

This is not true for the int-to-object conversion, however. Because int is a value type and object is a reference type. to maintain these semantics, the runtime needs to create a reference type wrapper around that int in order to do the conversion, "boxing" it.

This means that the runtime cannot just "do nothing" if it wants to convert a IEnumerable<int> to IEnumerable<object>. You would expect to get reference types out of that IEnumerable, not value types, so when and how does the "boxing" happen? When and how should this happen in general, not just in the case of IEnumerable<T>?

I'm sure this in theory can all be figured out, designed, and implemented, but it would certainly not be as trivial as the case with implicit reference conversions. In fact, I reckon it would be a lot more complicated and very drastic changes to both the language and runtime would be needed, which is probably why this is not implemented.

CodePudding user response:

Int is a value type while string is a reference type. Thus int is not an object whilst string is one.

See also here.

  • Related