2

I understand what is "T" in Generics as in this instance:

public interface IEquatable<T>
{            
    bool Equals(T other);
}

But don't understand "in T" as in this instance:

public interface IComparer<in T>
{            
    int Compare(T x, T y);
}

and "out T" as in this instance:

public interface IEnumerable<out T> : IEnumerable
{            
    IEnumerator<T> GetEnumerator();
}

Can someone please help me understand this??

kashif
  • 3,713
  • 8
  • 32
  • 47

2 Answers2

9

<out T> denotes that T is covariant.

It seems plausible that a sequence of giraffes can be treated as a sequence of animals. "Covariance" of an interface means that "if there is an implicit reference conversion from Giraffe to Animal then there is also an implicit reference conversion from I<Giraffe> to I<Animal>. The convertibility of the constructed type "varies in the same direction" as the convertibility of the type arguments.

Example:

// Valid!                                // Invalid!
// Every giraffe is an animal            // Not every animal is a giraffe
IEnumerable<Giraffe> giraffes = ...;     IEnumerable<Animal> animals = ...;
IEnumerable<Animal> animals = giraffe;   IEnumerable<Giraffe> giraffes = animals;
Animal animal = animals.First();         Giraffe giraffe = giraffes.First();

<in T> denotes that T is contravariant.

It seems plausible that code which can compare two animals can also compare two giraffes. "Contravariance" of an interface is the same as covariance with the direction reversed. It means that "if there is an implicit reference conversion from Giraffe to Animal then there is also an implicit reference conversion from I<Animal> to I<Giraffe>. The convertibility of the constructed type "varies in the opposite direction" as the convertibility of the type arguments.

Example:

// Valid!                                // Invalid!
// Animal comparer can compare           // Giraffe comparer cannot compare
// giraffes                              // arbitrary animals
IComparer<Animal> animalC = ...;         IComparer<Giraffe> giraffeC = ...;
IComparer<Giraffe> giraffeC = animalC;   IComparer<Animal> animalC = giraffeC;
int result = giraffeC.Compare(x, y);     int result = animalC.Compare(x, y);

See:

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
dtb
  • 213,145
  • 36
  • 401
  • 431
  • 1
    @kashif, why on earth have you specifically asked for a 'Jon Skeet' link?! – Arran Feb 21 '13 at 14:54
  • @dtb somebody suggested me to do that. I asked you what is more drived and less drived as well?? – kashif Feb 21 '13 at 14:55
  • If you have a `class Animal` and a `class Giraffe : Animal` then `Giraffe` is more derived than `Animal`, and `Animal` is less derived than `Giraffe`. – dtb Feb 21 '13 at 15:02
  • 1
    You have given definitions not of covariance and contravariance, but rather of *return type covariance* and *parameter type contravariance*. But these are not kinds of variance that C# supports! Your definitions should rather say "If an interface `I` is covariant in T and D has an implicit reference conversion to B, then there is also an implicit reference conversion from `I` to `I`. Contravariance is the opposite: `I` is convertible to `I`. – Eric Lippert Feb 21 '13 at 15:22
  • @EricLippert: I just quoted http://msdn.microsoft.com/en-us/library/dd233059.aspx – dtb Feb 21 '13 at 15:31
  • 1
    Oh for pete's sake, they were supposed to run all that documentation by me. Apparently they missed a page. Thanks for bringing this to my attention. Looks like I'll be having a chat with the MSDN manager this morning... – Eric Lippert Feb 21 '13 at 15:33
  • I tried to get the terminology right by quoting MSDN instead of trying to explain it myself. Feel free to edit my answer, or add your own answer so I can delete mine :-) – dtb Feb 21 '13 at 15:38
  • There are a number of smaller errors on that page as well; I am now quite sure it was never edited by me. I've sent a critique to the MSDN documentation manager and hopefully they will improve it. As requested I'll fix up your answer a bit. – Eric Lippert Feb 21 '13 at 16:21
  • @EricLippert and dtb thanks alot. you really helped me in understanding the concept of Covariance and Contravariance in c# – kashif Feb 22 '13 at 08:59
3

You could read about generic covariance and contravariance which was introduced in .NET 4.0. Eric Lippert also has a series of blog posts on this topic.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928