JoshBerke
JoshBerke

Reputation: 67068

Why do we need new keywords for Covariance and Contravariance in C#?

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

Answers (5)

Edward Kmett
Edward Kmett

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

Joel Coehoorn
Joel Coehoorn

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

Scott Dorman
Scott Dorman

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

James Curran
James Curran

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

yfeldblum
yfeldblum

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

Related Questions