Translate

Saturday, October 12, 2013

Covariant and contravariant generic interface C#

Covariance

If the type T is marked as "out" in a generic interface, then that means the interface will only output T. It doesnot have any method that takes T as an input. An example of a Covariant interface in .net is IEnumerable<T>. This interface is defined as

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


Significance:
What this practically means is that, in place of T, you can give it a child class of T.

For example if its expecting a List of objects you can give a List of strings.

using System;
using System.Collections.Generic;

namespace ConsoleApplication5
{
  
    internal class Program
    {
        private static void Main(string[] args)
        {
            var s = "";
            var o=new object();

            IEnumerable<string> strings;
            IEnumerable<object> objects;

            objects=new List<string>();//allowed 
            strings = new List<object>();//Throws Compile time error
        }
    }

    
}


Contravariance

This is the opposite of Covariance. If a type T is marked "in" in a generic interface, then that means that the interface has methods that accept T as an input and no methods in this interface output T. In the .net framework IComparer<T> is contravariant.


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

Significance

 In place of T you can give it a Parent of T.

For example 

using System;
using System.Collections.Generic;

namespace ConsoleApplication5
{


    internal class Program
    {
        private static void Main(string[] args)
        {
            var s = "";
            var o = new object();

            var strings = new List<string>();


            IComparer<Animal> a1 = new ObjectComparer();//allowed
            IComparer<Animal> a2 = new PersonComparer();//throws compile time error

        }
    }
    public class Animal
    {

    }

    public class Person : Animal
    {


    }

    public class ObjectComparer : IComparer<object>
    {


        public int Compare(object x, object y)
        {
            return 0;
        }
    }

   

    public class  PersonComparer : IComparer<Person>
    {
        public int Compare(Person x, Person y)
        {
            return 0;
        }
    }




}


No comments:

Post a Comment

Comments will appear once they have been approved by the moderator