Question

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

Was it helpful?

Solution

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?).

OTHER TIPS

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.

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.

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top