How to compare objects that is in a collection

So here is something that i encountered alot and i found it quite difficult and -not in my memory- all the time so i thought, OK lets write about it for my future reference and for others as well.

Problem Statement: 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

public class Animal
{
public FourLeggedAnimal FourLegged { get; set; }
}

public class FourLeggedAnimal
{
public String Name { get; set; }
}

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

 private static List<Animal> _animalList;
 public static void CheckCompare()
 {
 _animalList = new List<Animal>();
 var lionFourLegged = new FourLeggedAnimal() { Name = "Lion" };
 var elephantFourLegged = new FourLeggedAnimal() { Name = "Lion" };
 _animalList.Add(new Animal() { FourLegged = lionFourLegged });
 _animalList.Add(new Animal() { FourLegged = elephantFourLegged });

 var alionFourLegged = new FourLeggedAnimal() { Name = "Lion" };
 if(_animalList.Contains(new Animal(){FourLegged = alionFourLegged }))
 Console.WriteLine("We already have a lion");
 else
 Console.WriteLine("This is the first lion");
 Console.ReadLine();
 }

The output is “This is the first lion” which is not so what we need to do is the following

public class Animal
{
public FourLeggedAnimal FourLegged { get; set; }

public override bool Equals(object obj)
{
var animalToCompareTo =(Animal) obj;
if (FourLegged.Name.Equals(animalToCompareTo.FourLegged.Name)) return true;
return false;
}
}

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.

public class Animal : IEquatable<Animal>
{
public FourLeggedAnimal FourLegged { get; set; }
public override int GetHashCode()
{
var i = FourLegged.Name.GetHashCode();
return i;
}
public override bool Equals(Object obj)
{
if (FourLegged.Name.Equals(((Animal)(obj)).FourLegged.Name)) return true;
return false;
}
public virtual bool Equals(Animal other)
{
if (FourLegged.Name.Equals(other.FourLegged.Name)) return true;
return false;
}
}

We need GetHashCode(to return the hash code), Equals(Object) (For invariant types) and Equals(Animal) (for typed cases).