Compare Objects that is in a Collection

Problem

I have an object and when i use it in collection the Contains or certain comparison method does not work why is that?

Reason

In c# you have the flexibility of using using collection with your own objects but when you use them in a collection and try to call there comparison method the problem the base class comparison method is invoked which treats every object as a separate object and in return you will get different object every time even though they are identical.

Solution: To get a better understanding lets see that in the code.

We will use List, Distionary, ArrayList and HashSet.

Consider i have a class of Animal and i want to make a collection of Animal so lets see how this will be done in different case. Also i have another class which is part of animal that is FourLeggedAnimal so here is the code

  1. public class Animal  
  2. {  
  3.     public FourLeggedAnimal FourLegged  
  4.     {  
  5.         get;  
  6.         set;  
  7.     }  
  8. }  
  9. public class FourLeggedAnimal  
  10. {  
  11.     public String Name  
  12.     {  
  13.         get;  
  14.         set;  
  15.     }  
  16. }  

List and ArrayList: So let us try the code with list which is the same of List or ArrayList:

  1. private static List < Animal > _animalList;  
  2. public static void CheckCompare()  
  3. {  
  4.     _animalList = new List & lt;  
  5.     Animal & gt;  
  6.     ();  
  7.     var lionFourLegged = new FourLeggedAnimal()  
  8.     {  
  9.         Name = "Lion"  
  10.     };  
  11.     var elephantFourLegged = new FourLeggedAnimal()  
  12.     {  
  13.         Name = "Lion"  
  14.     };  
  15.     _animalList.Add(new Animal()  
  16.     {  
  17.         FourLegged = lionFourLegged  
  18.     });  
  19.     _animalList.Add(new Animal()  
  20.     {  
  21.         FourLegged = elephantFourLegged  
  22.     });  
  23.     var alionFourLegged = new FourLeggedAnimal()  
  24.     {  
  25.         Name = "Lion"  
  26.     };  
  27.     if (_animalList.Contains(new Animal()  
  28.         {  
  29.             FourLegged = alionFourLegged  
  30.         }))  
  31.         Console.WriteLine("We already have a lion");  
  32.     else  
  33.         Console.WriteLine("This is the first lion");  
  34.     Console.ReadLine();  
  35. }   
The output is “This is the first lion” which is not so what we need to do is the following:
  1. public class Animal  
  2. {  
  3.     public FourLeggedAnimal FourLegged  
  4.     {  
  5.         get;  
  6.         set;  
  7.     }  
  8.     public override bool Equals(object obj)  
  9.     {  
  10.         var animalToCompareTo = (Animal) obj;  
  11.         if (FourLegged.Name.Equals(animalToCompareTo.FourLegged.Name)) return true;  
  12.         return false;  
  13.     }  
  14. }  
So now i have extended my class and the next output will be “We already have a lion”.

HashSet and Dictionary: To make it work with HasSet and dictionary we need to do the following changes in the animal class. You need to implement from IEquatable interface which is type safe and you wont have any boxing/unboxing issues while comparision.

  1. public class Animal: IEquatable < Animal >  
  2. {  
  3.     public FourLeggedAnimal FourLegged  
  4.     {  
  5.         get;  
  6.         set;  
  7.     }  
  8.     public override int GetHashCode()  
  9.     {  
  10.         var i = FourLegged.Name.GetHashCode();  
  11.         return i;  
  12.     }  
  13.     public override bool Equals(Object obj)  
  14.     {  
  15.         if (FourLegged.Name.Equals(((Animal)(obj)).FourLegged.Name)) return true;  
  16.         return false;  
  17.     }  
  18.     public virtual bool Equals(Animal other)  
  19.     {  
  20.         if (FourLegged.Name.Equals(other.FourLegged.Name)) return true;  
  21.         return false;  
  22.     }  
  23. }   
We need GetHashCode(to return the hash code), Equals(Object) (For invariant types) and Equals(Animal) (for typed cases).