Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

covariance/contravariance in C#

I have a book that explains contravariance/covariance as follows :

  • a delegate can have more specific parameter types than its method target. This is called contravariance
  • the return type of a delegate can be less specific than the return type of its target method. This is called covariance

And, this is an example.

using System;

delegate void StringAction(string s);
delegate object ObjectRetriever();

class Test
{
    static void Main()
    {
        StringAction sa = new StringAction(ActionObject);
        sa("hello");

        ObjectRetriever o = new ObjectRetriever(RetrieveString);
        object result = o();
        Console.WriteLine(result);
    }


    static string RetrieveString() {return "hello";}

    static void ActionObject(object o)
    {
        Console.WriteLine(o);
    }
}

I thought in order to use covariance/contravariance, one needs to use new as is shown in the example, but I seem to get the same result with sa = ActionObject and o = RetrieveString. (I tested with Mono).

  • Then, why the writer uses new to explain covariance/contravariance?
  • What's the theory behind the covariance/contravariance idea? Is it just a fancy name describing object x = Everything inherit from object? Where is this weird name come from? What's the usage for it?
like image 829
prosseek Avatar asked Jul 23 '11 01:07

prosseek


People also ask

What is covariance in programming?

Covariance means that a method can return a type that is derived from the delegate's return type. Contra-variance means that a method can take a parameter that is a base of the delegate's parameter type.

What is covariance and contravariance in Java?

Covariance can be translated as "different in the same direction," or with-different, whereas contravariance means "different in the opposite direction," or against-different. Covariant and contravariant types are not the same, but there is a correlation between them. The names imply the direction of the correlation.

What is array covariance?

You can also assign an array of objects of a more derived type to an array of objects of a base type. This is known as array covariance. It's allowed as long as the type of the source array elements is implicitly convertible to the type of the target array elements.


2 Answers

I have a book that explains contravariance/covariance as follows ...

That is not a very good explanation of variance. It is left completely unclear precisely what it is that is called "covariance" and "contravariance".

The thing that actually is variant is never mentioned. The thing that is contravariant is the mapping from a type to a delegate with a parameter of that type. Contravariance is a property of mappings and relationships.

Try reading this and see if you understand it any better:

http://blogs.msdn.com/b/ericlippert/archive/2007/10/19/covariance-and-contravariance-in-c-part-three-member-group-conversion-variance.aspx

I thought in order to use covariance/contravariance, one need to use new as is shown in the example, but I seem to get the same result ...

Ever since C# 2.0 you can say either "d = M" or "d = new D(M)" -- the compiler simply recognizes them as two different ways to write the same thing.

why the writer uses new to explain covariance/contravariance?

I don't know.

What's the theory behind the covariance/contravariance idea?

The theory is that if you have an ordering relationship -- that is, X is bigger than Y if it is legal to say X x = (Y)y -- and you have a mapping that preserves the ordering relationship, then the mapping is covariant. If it reverses the ordering relationship, it is contravariant.

For example, suppose Animal is a bigger type than Giraffe. So you can assign an object of type Giraffe to a variable of type Animal. Animal > Giraffe.

Now make a mapping from a type T to a method M-that-takes-a-T and to a delegate type D-that-takes-a-T.

You can assign a method M-that-takes-an-Animal to a variable of type D-that-takes-a-Giraffe. D(Giraffe) > M(Animal) but Animal > Giraffe. The relationship is reversed; the mapping is contravariant.

Is it just a fancy name describing object x = Everything inherit from object?

No. It is related to that concept because object is a larger type than almost every other type. But what is actually variant is a mapping that preserves or reverses a size relationship.

Try reading this and see if it helps.

http://blogs.msdn.com/b/ericlippert/archive/2009/11/30/what-s-the-difference-between-covariance-and-assignment-compatibility.aspx

Where is this weird name come from?

Category theory.

like image 175
Eric Lippert Avatar answered Nov 02 '22 19:11

Eric Lippert


The best info describing covariance/contravariance in the C# I've ever seen is series of blog posts by Eric Lippert here. See starting from the bottom of the list, eleven-parts series.

It is somewhat hard to read sometimes. But it explains everything you could ask in the beginning. :)

It was written prior to actual C# 4.0 implementation, so some discussion of the syntax is obsolete, but everything else seems to be implemented just as described.

like image 33
Ivan Danilov Avatar answered Nov 02 '22 20:11

Ivan Danilov