Can someone explain the usage of the out T part with an example?
Sure. IEnumerable<T>
is covariant. That means you can do this:
static void FeedAll(IEnumerable<Animal> animals)
{
foreach(Animal animal in animals) animal.Feed();
}
...
IEnumerable<Giraffe> giraffes = GetABunchOfGiraffes();
FeedAll(giraffes);
"Covariant" means that the assignment compatibility relationship of the type argument is preserved in the generic type. Giraffe
is assignment compatible with Animal
, and therefore that relationship is preserved in the constructed types: IEnumerable<Giraffe>
is assignment compatible with IEnumerable<Animal>
.
Why is applicable only for interfaces and delegates and not for classes?
The problem with classes is that classes tend to have mutable fields. Let's take an example. Suppose we allowed this:
class C<out T>
{
private T t;
OK, now think this question through carefully before you go on. Can C<T>
have any method outside of the constructor that sets the field t
to something other than its default?
Because it must be typesafe, C<T>
can now have no methods that take a T as an argument; T can only be returned. So who sets t, and where do they get the value they set it from?
Covariant class types really only work if the class is immutable. And we don't have a good way to make immutable classes in C#.
I wish we did, but we have to live with the CLR type system that we were given. I hope in the future we can have better support for both immutable classes, and for covariant classes.
If this feature interests you, consider reading my long series on how we designed and implemented the feature. Start from the bottom:
https://blogs.msdn.microsoft.com/ericlippert/tag/covariance-and-contravariance/
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…