views:

70

answers:

1

Hi,

I'm at the point where I'm starting to grasp contravariance, although I'm trying to work out what the advantage is when an interface can be used instead. Obviously I'm missing something.

Here is the c#4 example

class Dog : Animal {
        public Dog(string name) : base(name) { }
    }

    class Animal {

        string _name;

        public Animal(string name) {
            _name = name;
        }

        public void Walk() {
            Console.WriteLine(_name + " is walking");
        }
    }

 Action<Animal> MakeItMove = (ani) => { ani.Walk(); };

            Action<Dog> MakeItWalk = MakeItMove;

            MakeItWalk(new Dog("Sandy"));

Same example which works in earlier versions on c#

class Dog : Animal {
        public Dog(string name) : base(name) { }
    }

    class Animal : IAnimal {

        string _name;

        public Animal(string name) {
            _name = name;
        }

        public void Walk() {
            Console.WriteLine(_name + " is walking");
        }
    }

    interface IAnimal {

        void Walk();
    }

    Action<IAnimal> MakeItMove = (ani) => { ani.Walk(); };

                Action<IAnimal> MakeItWalk = MakeItMove;

                MakeItWalk(new Dog("Sandy"));

These may not be the best examples, but I still can't seem to 'get it'. Is the in keywork defined on the action delegate simply a short hand syntax way like lamda is to delegates?

+2  A: 

Contravariance is the reason why this works with interfaces. Method calls allow argument type contravariance (and return type covariance).

It's okay for there to be more than one way to solve the same problem.

Consider that sometimes you don't have control over the class structure. What if you can't change the definition of Dog? Your task suddenly just became a lot harder without type variance.

Covariance and contravariance aren't problems to be solved, they are language features, like generic types. Everything that you can do with generic types, you could do in .NET 1.x before generic types existed and can still do with a lot of boxing and casting. Should you? That depends entirely on your requirements.

Aaronaught
+1, Not to mention some things (like Delegates and Enums) can't implement interfaces.
Josh Einstein