Subscribe to andrewsw's Blog        RSS Feed
-----

Co and Contravariance, briefly

Icon Leave Comment
Covariance and Contravariance in Generics

MSDN said:

Covariance

Enables you to use a more derived type than originally specified.

You can assign an instance of IEnumerable<Derived> (IEnumerable(Of Derived) in Visual Basic) to a variable of type IEnumerable<Base>.

Contravariance

Enables you to use a more generic (less derived) type than originally specified.

You can assign an instance of IEnumerable<Base> (IEnumerable(Of Base) in Visual Basic) to a variable of type IEnumerable<Derived>.


using System;
using System.Collections.Generic;

namespace CoAndContra {
    class Animal {
        public virtual void Statement() {
            Console.WriteLine("I'm an Animal!");
        }
    }
    class FruitBat : Animal {
        public new void Statement() {
            Console.WriteLine("I'm a FruitBat!");
        }
    }
    class DingBat : Animal {
        public new void Statement() {
            Console.WriteLine("I'm a DingBat!");
        }
    }

    class Program {
        static void Main(string[] args) {

            // Polymorphism

            // Polymorphism (C# Programming Guide)
            // https://msdn.microsoft.com/en-in/library/ms173152(v=vs.110).aspx

            List<Animal> animals = new List<Animal>();
            animals.Add(new FruitBat());
            animals.Add(new FruitBat());

            foreach (Animal anim in animals) {
                anim.Statement(); // I'm an Animal!, twice
                // change "new" to "override" and it will print FruitBat instead
            }

            foreach (Animal anim in animals) {
                // we can cast because each anim is a FruitBat 
                ((FruitBat)anim).Statement(); // I'm a FruitBat!, twice
            }

            //animals.Add(new DingBat());

            //foreach (Animal anim in animals) {
            //    // we cannot cast a DingBat to a FruitBat 
            //    ((FruitBat)anim).Statement(); // InvalidCastException
            //}

            // Covariance

            // Covariance and Contravariance in Generics
            // https://msdn.microsoft.com/en-in/library/dd799517(v=vs.110).aspx

            // IEnumerable is covariant (the out keyword):
            //  public interface IEnumerable<out T> : IEnumerable {
            //      [__DynamicallyInvokable]
            //      IEnumerator<T> GetEnumerator();
            // } / (code from dotPeek)

            IEnumerable<FruitBat> bats = new List<FruitBat>() { new FruitBat(), new FruitBat() };

            // because IEnumerable is covariant we can do this:
            IEnumerable<Animal> anims = bats;

            foreach (Animal anim in anims) {
                anim.Statement(); // I'm an Animal!, twice
            }
            // this looks much like ordinary polymorphism

            // Contravariance

            // The parameter T in Action<T> is contravariant (in):
            // public delegate void Action<in T>(T obj);

            Action<Animal> animalAction = (obj) => { Console.WriteLine(obj.GetType().Name); };

            // because of this contravariance we can do this:
            Action<FruitBat> fruitbatAction = animalAction;

            fruitbatAction(new FruitBat()); // FruitBat


            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

0 Comments On This Entry

 

Trackbacks for this entry [ Trackback URL ]

There are no Trackbacks for this entry

December 2017

S M T W T F S
     12
3456789
10111213141516
17 18 1920212223
24252627282930
31      

Tags

    Recent Entries

    Recent Comments

    Search My Blog

    1 user(s) viewing

    1 Guests
    0 member(s)
    0 anonymous member(s)

    Categories