3/10/13

Generic Contravariance in C#

In my previous post .NET interfaces Part 3 I had written about the IEqualityComparer interface which has the following signature:

 public interface IEqualityComparer<in T>
 {
        bool Equals(T x, T y);        
        int GetHashCode(T obj);
 }
 
The keyword "in" before the type T indicates that this interface is contravariant.

In the same post we were calling the Contains method on a collection of type FootballStar as shown below:

FootballStars.Contains(Peyton2,new StarComparer())
We were passing in an instance of type IEqualityComparer<Star> to a method that was expecting an IEqualityComparer<FootballStar> i.e we were able to pass a less derived type than was specified by the type parameter.

This was possible because the interface IEqualityComparer<in T> is a contravariant interface that allows us to pass a less derived type than the specified type parameter.

Even though we are passing in a less derived type, everything works perfectly because the instances that ultimately get passed to the Equals method of the IEqualityComparer method are still of type FootballStar(since the collection is of type FootballStar), which derives from Star.

If the interface was not Contravariant, we would have to create a new IEqualityComparer of type FootballStar and pass that to the contains method. The compiler will not have it any other way. We would also have to repeat this for every type that derived from Star, assuming that all instances of type Star(e.g. FootballStar, BaseballStar) wish to use the same logic to determine the equality of their instances.

We would end up writing code like this:

//a comparer for FootballStar instances
public class FootballStarComparer:IEqualityComparer<FootballStar>
{
}
//that will be passed to contains FootballStars.Contains(Peyton2,new FootballStarComparer())

//a comparer for BaseballStar instances public class BaseballStarComparer:IEqualityComparer<BaseballStar> { }
//that will be passed to contains BaseballStars.Contains(bbStar1,new BaseballStarComparer())
So instead of using the type inheritance heirarchy and polymorphism we would be writing a lot of repititive code to perform similar tasks.

3/9/13

.NET interfaces Part 3

IEqualityComparer<T>

 public interface IEqualityComparer<in T>
 {
        bool Equals(T x, T y);        
        int GetHashCode(T obj);
 }
 
When to use it:
Let us say you have a custom Type and you plan to use instances of that type in a collection. If you want to use methods like List<T>.contains or Dictionary<T1,T2>.Add, you will need to way to check if an item in your collection equals the item we are trying to find.To facilitate this you can implement the IEqualityComparer<T>.

How is it different from IEquatable<T>?
For every custom type that you wish to check for Equality, you will need to implement the IEquatable<T> interface. But if you have a set of related base/child classes that share a common Equality check functionality, you need to create just one IEqualityComparer<T> where T is the Base type and use it with all other types.

public abstract class Star
    {
        public int Age { get; set; }
        public int GamesPlayed { get; set; }
        public int PointsScored { get; set; }
    }

    public class FootballStar : Star
    {
       
    }

    public class BaseballStar : Star
    {

    }

    //This comparer can be used by all instances of type Star 
    public class StarComparer: IEqualityComparer<Star>
    {
        //strongly typed input parameter
        public bool Equals(Star input1, Star input2)
        {
            if (input1.GamesPlayed == input2.GamesPlayed && 
                  input1.PointsScored == input2.PointsScored) 
               return true;
            return false;
        }
        
        public int GetHashCode(Star input)
        {
            //the XOR value
            return input.GamesPlayed ^ input.PointsScored;
        }
    }

    //calling code
    class Program
    {
        static void Main(string[] args)
        {
     FootballStar Brady = new FootballStar() 
                   { Age = 35, GamesPlayed = 900, PointsScored = 55000 };
            FootballStar Peyton = new FootballStar() 
                   { Age = 35, GamesPlayed = 500, PointsScored = 30000 };
            FootballStar Rodgers = new FootballStar() 
                   { Age = 28, GamesPlayed = 500, PointsScored = 31000 };
            FootballStar Griffin = new FootballStar() 
                   { Age = 28, GamesPlayed = 400, PointsScored = 20000 };

            List FootballStars = new List() 
                   {Brady, Peyton, Rodgers, Griffin};
            
            FootballStar Peyton2 = new FootballStar() 
                  { Age = 35, GamesPlayed = 500, PointsScored = 30000 };

            /* the Equals method of the comparer will be used to 
                  determine the equality
               */
    Console.WriteLine(FootballStars.Contains(Peyton2,new StarComparer()));

            /* Add internally calls GetHashCode of the StarComparer 
                  and will not let you add two keys with the same HashCode
               */
         Dictionary StarDictionary = new Dictionary(3,new StarComparer());
            StarDictionary.Add(Brady, "Patriots");
            StarDictionary.Add(Peyton, "Denver");
            StarDictionary.Add(Rodgers, "Greenbay");
            StarDictionary.Add(Griffin, "Washington");

            //Contains and ContainsKey will both internally call 
            //comparer's Equals and GetHashCode methods
            Console.WriteLine(StarDictionary.ContainsKey(Peyton2));
   Console.WriteLine(StarDictionary.Contains(new KeyValuePair(Peyton2, "Denver")));
 }
}
NOTE:
Since the type T of the comparer is of type Star, any types that derive from it can use the same equality comparer as long as they wish to use the same criteria for determining equality. e.g. if the instances of the type BaseballStar were used in a collection, we can use the same EqualityComparer to test for Equality since BaseballStar inherits from Star

.NET interfaces Part 2

IEquatable<T>

 public interface IEquatable<t>
 {       
   bool Equals(T other);
 }
When to use it:
Let us say you have a custom Type and you plan to use instances of that type in a collection. If you want to use methods like List<T>.contains or List<T>.IndexOf you will need to way to check if an item in your collection equals the item we are trying to find.To facilitate this your custom Type needs to implement the Equals method of IEquatable<T>.

NOTE: Since we are checking for equality, we need to override the default implementations of Object.Equals and Object.GetHashCode methods so that they are consistent with the IEquatable<T>.Equals method.

 public class BasketballStar : IEquatable<BasketballStar>
 {
 public int Age { get; set; }
 public int GamesPlayed { get; set; }
 public int PointsScored { get; set; }

     //The IEquatable's Equals method with a strongly typed 
     //input parameter
     public bool Equals(BasketballStar input)
     {
      if(this.GamesPlayed==input.GamesPlayed && 
         this.PointsScored==input.PointsScored) 
        return true;
      return false;
     }

       //overriding the base Equals to keep consistency with the 
       //Equatable's Equals
 public override bool Equals(object input)
 {
    BasketballStar objStar = input as BasketballStar;
    if (objStar == null) return false;
    return this.Equals(objStar);
 }

 /*
         override the base GetHashCode to be consistent with the 
         Equals methods Since we are basing equality based on games
         played and point scored, the hash code is also an XOR of 
         the same properties. So if two objects are equal, the Equals 
         method must return true and thier GetHashCode values must 
         be the same
        */
 public override int GetHashCode()
 {
    //the XOR value
    return this.GamesPlayed ^ this.PointsScored;
 }
 }

//calling code
class Program
{
   static void Main(string[] args)
   {
     BasketballStar Jordan = new BasketballStar() 
                   { Age = 50, GamesPlayed = 900, PointsScored = 55000 };
     BasketballStar Kobe = new BasketballStar() 
                   {Age = 35, GamesPlayed = 500, PointsScored = 30000};
     BasketballStar Lebron = new BasketballStar() 
                   { Age = 28, GamesPlayed = 500, PointsScored = 31000 };
     BasketballStar Durant = new BasketballStar() 
                   { Age = 28, GamesPlayed = 400, PointsScored = 20000 };
     BasketballStar Jordan2 = new BasketballStar() 
                   { Age = 50, GamesPlayed = 900, PointsScored = 55000 };

    //using a list
   List lstStars = new List();
   lstStars.Add(Jordan);
   lstStars.Add(Kobe);
   lstStars.Add(Lebron);
   lstStars.Add(Durant);

   //contains method internally calls the Equals 
          //method of IEquatable
   Console.WriteLine(lstStars.Contains(Jordan2));

   //using a dictionary
   Dictionary StarsDictionary = new Dictionary(3);

   //Add internally calls GetHashCode and will not let you add two 
          //keys with the same HashCode
   StarsDictionary.Add(Jordan, "Chicago Bulls");
   StarsDictionary.Add(Kobe, "Lakers");
   StarsDictionary.Add(Lebron, "Miami");
   StarsDictionary.Add(Durant, "Oklahoma");

   //the contains and containsKey methods both internally call the 
          //GetHashCode as well as the IEquatable's Equals method
   //so both of them need to return consistent values
   Console.WriteLine(StarsDictionary.ContainsKey(Jordan2));
   Console.WriteLine(StarsDictionary.Contains(new KeyValuePair(Jordan2, "chicago bulls")));
 }
}

3/5/13

.NET interfaces - Part 1

I was re-reading some .net basics a couple of weeks ago just to refresh my memory and I came across some core interfaces that I had used in the past.

At that time i was not blogging and hadn't had a chance to write any posts about them. So I was thinking now is probably a good time to do it.

IComparable<T>


public interface IComparable<in T>
{       
  int CompareTo(T other);
}
When to use it:
Let us say you have a custom Type and you plan to use instances of that type in a collection. Whenever you are dealing with collections one of the obvious requirements is that the items in the collection be sortable.To facilitate this your custom Type needs to implement the CompareTo method of IComparable.

Code is as follows:

public class Texas : IComparable
{
        public string Name { get; set; }
        public int Population { get; set; }

/*
This method compares the population of the current instance with the input instance.
returns 0 if they are equal, 1 if this instance's population is greater than the input's population
and -1 if this instance's population is less than the input's population
*/
public int CompareTo(Texas input)
{
   if (this.Population < input.Population) return -1;
   if (this.Population == input.Population) return 0;
   return 1;
} 
}

//calling code

class Program
{

 static void Main(string[] args)
 {

  List lstTexas = new List();

  lstTexas.Add(new Texas() {Name = "Austin", Population = 500});
  lstTexas.Add(new Texas() {Name = "Houston", Population = 1500});
  lstTexas.Add(new Texas() {Name = "Dallas", Population = 900});
  lstTexas.Add(new Texas() {Name = "San Antonio", Population = 1200});
  lstTexas.Add(new Texas() {Name = "Waco", Population = 200});

  /*
     Sort internally calls the CompareTo method.The CompareTo method is 
     usually not called explicitly but is called from methods
     like the List<T>.Sort or Add(in a sorted list)
  */
   lstTexas.Sort();

  foreach (Texas city in lstTexas)
   Console.WriteLine(city.Name);

 }

}


//output - the cities are sorted in the ascending order of their populations
Waco
Austin
Dallas
San Antonio
Houston

NOTE: When you call Sort() with no arguments, you can only sort in ascending order OR descending order depending on your logic inside the CompareTo method. If you wish you can specify a sort order by using the overload of Sort that takes a Comparision delegate as an argument.