I would disagree with the other answers.. Animal in this example is not a value object, it's perfectly feasable that two cats could have the same name & colour and be completely distinct entities. Logically you're saying "this cat and that cat have the same name and the same colour, therefore they are the same cat" - which is not necessarily true..
What I would suggest you do is leave Animal.Equals to the default implementation, and create a seperate IEqualityComparer implementation that returns true if the animals have the same name/colour.
public class AnimalNameColorComparer : IEqualityComparer<Animal>
{
public bool Equals(Animal a, Animal b)
{
return a.Name == b.Name &&
a.Color == b.Color
}
public int GetHashCode(Animal a)
{
return a.Name.GetHashCode() ^ a.Color.GetHashCode();
}
}
Try to remember that there are many different ways to compare a cat, and one single "Equals" method is not enough :)
// Create two black cats called fluffy...
var cat1 = new Cat("Fluffy", "Black");
var cat2 = new Cat("Fluffy", "Black");
cat1.Equals(cat2) == false; // they are not the same cat!
var comparer = new AnimalNameColorComparer();
comparer.Equals(cat1, cat2) == true; // But they do have the same name & colour...