I was wondering , why does IEnumerable<T>
has ONLY the out
and not the in
contravariant flag ?
public interface IEnumerable<out T>
I can understand the out
by this example :
IEnumerable<string> strings = new List<string>(){"a","b","c"};
IEnumerable<object> objects = strings;
object
is bigger than string
, so the compiler afraid that well do something like:
objects = objects.First().Select(x=>5);// ( we cant insert int to string...)
fine and understood.
but what about if i want to use the IEnumerable as insertion?
something like :
IEnumerable<object> objects = ...;
IEnumerable<string> strings = objects
so i can also INSERT into objects ...
but the problem is that there is no IEnumerable<in T>
...
am I missing something here?
Eric Lippert has a series of posts on this prior to introducing co/contravariance in C# which is worth a read.
a simple example would be
in other words there's no way the compiler can guarantee that you can safely use your
IEnumerable<Animal>
as anIEnumerable<Giraf>
. All girafs are animals but not all animals are girafsI think it's strictly realted to type safity: what if you in your list
IEnumerable<object> {"Hello", 2.34d, new MyCoolObject(), enumvalue}
?How runtime should treat those conversions ?
In case of
string
it could be a simple case, cause it should be enough to call override (if any) ofToString()
, but framework designer can not rely on custom cases and should provide generic solutions.Hope this helps.
You can't assign
IEnumerable<Parent>
toIEnumerable<Child>
because it may contain elements that are notChild
.There is no way to know at compile time that the
IEnumerable<object>
doesn't contain a non-string
. However, if you (the programmer) know there are onlystring
s there, you can do the casting at run-time:Incidentally, you might want to take a look at description of the tag covariance.
You can't insert into
IEnumerable
. There is, unfortunately, no "IInsertable".There is no interface to tell that you can only add items to a collection. This would be an
in
generic type. Because you can get the items on every collection interface, it is not possible to havein
generic arguments.Edit
The interface
IEnumerable<T>
has only getters, so you can't insert any elements to the collection using that interface. Because of that,out
is allowed in the declaration ofIEnumerable<out T>
. It tells the compiler, that values of typeT
are only going in one direction, the are "coming out". This makes it compatible in one direction. You can useIEnumerable<string>
as anIEnumerable<object>
, because you are only reading from it. You can read a string as an object. But you couldn't write to it, you couldn't pass an object as a string. It might be an integer or any other type.As already mentioned in the comments, you cannot use IEnumerable to modify a collection.
The compiler will not allow code like the one below due to type safety issues as the one you mentioned (inserting int to an list of string) because you can modify the strings lists here using objects
IEnumerable is simply an iterator over a collection.
Hope this helps.
I don't see your problem here. When using
IEnumerable
you can't insert, and that is not what you are doing. What you are trying to do is assigning aIEnumerable<string>
a value ofIEnumerable<object>
and that won't work. When you are assigning yourIEnumerable<string>
with an object that is of typeIEnumerble<object>
you can't guarantee that all the objects in the list is of type string. That is why can't do that.Covariant, the
out
keyword, interfaces ensures that the output can always be understood by the consuming part, that is, anIEnumerable<string>
can be casted to a list ofIEnumerable<object>
sincestring : object
and someone consuming a list ofobject
must know how to handle astring
but not the other way around.Contravariant, the
in
keyword, interfaces enables you to cast objects to less specified generics, that is,IComparer<object>
can be casted toIComparer<string>
since a class implementingIComparer<object>
must now how to handlestring
since it is contravariant but not the other way around.Read more here: http://msdn.microsoft.com/en-us/library/dd799517.aspx