Assume we have a complex structure containing some other complex types, even possibly containing itself e.g.
public class Box {
public string Name { get; set; }
public List<Box> Boxes { get; set; }
public List<Item> Items { get; set; }
public SomeOtherComplexType BlaBla { get; set; }
...
}
And we need to have a possibility to compare these complex types.
Since overriding object.Equals() will be of a poor perfomance when it comes to generic types I see a lot of usages of IEquatable<>.
The problem is that using IEquatable<> uglifies the code very much mixing the business logic and the technical part of overriding the Equeals() and GetHashCode() methods. And the more bigger our structure is - the larger overridden methods are.
It looks awful and oblige to do the same for all inner types.
public class Box : IEquatable<Box> {
public string Name { get; set; }
public List<Box> Boxes { get; set; }
public List<Item> Items { get; set; }
public SomeOtherComplexType BlaBla { get; set; }
public bool Equals(Box other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return
(
Name == other.Name||
Name != null &&
Name.Equals(other.Name)
) &&
(
Boxes == other.Boxes ||
Boxes != null &&
Boxes.SequenceEqual(other.Boxes)
) &&
(
Items == other.Items ||
Items != null &&
Items.SequenceEqual(other.Items)
) &&
(
BlaBla == other.BlaBla ||
BlaBla != null &&
BlaBla.SequenceEqual(other.BlaBla)
);
}
public override int GetHashCode()
{
unchecked
{
var hashCode = 14;
if (Name != null)
hashCode = hashCode * 14 + Name.GetHashCode();
if (Boxes != null)
hashCode = hashCode * 14 + Boxes.GetHashCode();
if (Items != null)
hashCode = hashCode * 14 + Items.GetHashCode();
if (BlaBla!= null)
hashCode = hashCode * 14 + BlaBla.GetHashCode();
return hashCode;
}
}
}
Are there any ways of making it less worse or maybe some other alternatives.
Maybe some ways to hide this implementation and make it as much automated as possible? There are only 4 fields, but what if we are having some complex types with ~30 types in it, with some nested types etc??
Using something like hybrid composite design pattern seems to be even more complex to implement.