开发者

Can't contravariance be implemented with interfaces?

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 lambda is to delegates?


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜