Reputation: 67068
Can someone explain why there is the need to add an out or in parameter to indicate that a generic type is Co or Contra variant in C# 4.0?
I've been trying to understand why this is important and why the compiler can't just figure it out..
Thanks,
Josh
Upvotes: 17
Views: 1944
Reputation: 29962
Well, the main problem is that if you have a class hierarchy like:
class Foo { .. }
class Bar : Foo { .. }
And you have an IEnumerator<Bar>
, you can't use that as an IEnumerator<Foo>
even though that would be perfectly safe. In 3.5 this forces a large number of painful gyrations. This operation would always be safe but is denied by the type system because it doesn't know about the covariant use of the generic type parameter. IEnumerator<Bar>
can only return a Bar
and every Bar
is a Foo
.
Similarly, if you had an IEqualityComparer<Foo>
it can be used to compare any pair of objects of type Foo
even if one or both is a Bar
, but it cannot be cast into an IEqualityComparer<Bar>
because it doesn't know about the contravariant use of the generic type parameter. IEqualityComparer<Foo>
only consumes objects of type Foo
and every Bar
is a Foo
.
Without these keywords we're forced to assume the generic argument can occur as both an argument to a method and as the result type of a method, and so we can't safely allow either of the above conversions.
With them, the type system is free to allow us to safely upcast and downcast between those interfaces in the direction indicated by the keyword and we get errors indicating when we would violate the discipline required to ensure that safety.
Upvotes: 6
Reputation: 415735
Eric Lippert, who works on the langauge, has a series of posts on msdn that should help clarify the issues involved:
http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
When reading the articles shown at that link, start at the bottom and work up.
Eventually you'll get to #7 (Why do we need a syntax at all?).
Upvotes: 18
Reputation: 42516
Jon and Joel both provided a pretty complete answer to this, but the bottom line is that they aren't so much needed by the compiler but rather help guarantee the safety of the implementation by explicitly indicating the variance of the parameter. This follows a very similar pattern to requiring the out
or ref
keyword at both the calling site and the declaration site.
Upvotes: 1
Reputation: 103505
We don't actually need them, any more then we need abstract
on classes or both out
and ref
. They exist just so that we, as programmers, can make our intention crystal clear, so that maintenance programmer know what we are doing, and the compiler can verify that we are doing it right.
Upvotes: 7
Reputation: 65435
The in
and out
keywords have been keywords since C# 1.0, and have been used in the context of in
- and out
- parameters to methods.
Covariance and contravariance are constraints on how one can implement an interface. There is no good way to infer them - the only way, I think, is from usage, and that would be messy and in the end it wouldn't work.
Upvotes: 1