According to this MSDN reference IEnumerable
is covariant and this is possible to implicitly cast a list of objects to an enumerable:
IEnumerable<String> strings = new List<String>();
IEnumerable<Object> objects = strings;
In my own code i have written a line of code that works perfect when item type of the list is class Point
(Point is a simple class with three properties double x,y,z):
var objects = (IEnumerable<object>)dataModel.Value;
// here property Value is a list that could be of any type.
But the above code returns the following exception when item type of the list is double
:
Unable to cast object of type System.Collections.Generic.List1[System.Double]
to type System.Collections.Generic.IEnumerable1[System.Object].
What is the difference between string
and double
and what causes the code to work with string
but not with double
?
According to this post we could simply cast a list to IEnumerable
(without type argument) so as I only need to iterate over items and add new items to the list ( Actually I do not need to cast items of the list, at all). I decided to use this one:
var objects = (IEnumerable)dataModel.Value;
But if you need to cast items of the list to object
and use them, the answer from Theodoros is the solution you most follow.
In C#, an IEnumerable can be converted to a List through the following lines of code: IEnumerable enumerable = Enumerable. Range(1, 300); List asList = enumerable. ToList();
IEnumerable is an interface defining a single method GetEnumerator() that returns an IEnumerator interface. It is the base interface for all non-generic collections that can be enumerated. This works for read-only access to a collection that implements that IEnumerable can be used with a foreach statement.
IEnumerable in C# is an interface that defines one method, GetEnumerator which returns an IEnumerator interface. This allows readonly access to a collection then a collection that implements IEnumerable can be used with a for-each statement.
Constructed types of variant interfaces (such as IEnumerable<out T>
) are variant only for reference type arguments, because their implicit conversion to a supertype (such as object
) is a non-representation-changing conversion. This is why IEnumerable<string>
is covariant.
Constructed types for value type arguments are invariant, because their implicit conversion to a supertype (such as object
) is representation-changing, due to the boxing that's required. This is why IEnumerable<double>
is invariant.
See the relevant documentation:
Variance applies only to reference types; if you specify a value type for a variant type parameter, that type parameter is invariant for the resulting constructed type.
A possible workaround is to use LINQ cast:
var sequence = list.Cast<object>();
This will first check whether the source is assignment-compatible to the IEnumerable<TResult>
that you are trying to cast it to.
T
being string
, for example), it will return the initial source directly (which is the ideal case, performance-wise).T
being double
, for example), it will create a projection that attempts the conversion manually for each individual element.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With