c# equality check for class containing reference type properties

75 Views Asked by At

If we have a class that contains properties/fields of other reference types, how would a proper and elegant equality check be performed?

For example, MainClass contains properties of SubClassA and SubClassB. We can assume that all of these classes override object.Equals with the same implementation, what would that be?

I came up with the following which doesn't look very nice. My logic is as follows:

  1. We cannot use Equals directly on the reference types because they can be null, so we first check if only one of them is null, which leads to inequality.

  2. Then, if both have a value, make sure the value is equal.

  3. We can omit the check that they are both null as it leads to equality.

    class MainClass {
        SubClassA A {get; set;}
        SubClassB B {get; set;}
        int someint {get; set;}
    
        public override bool Equals(object obj) {
            MainClass other = obj as MainClass;
            if (other is null)
                return false;
    
            // First check if only one of the As is null.
            if (A is null ^ other.A is null) {
                return false;
            }
            // Then check if both have a value that the value is equal.
            else if (A != null && other.A != null && !A.Equals(other.A)) {
                return false;
            }
            // Case where As are both null is omitted as it leads to equality.
    
            // Same principle here and for any other reference types...
            if (B is null ^ other.B is null) {
                return false;
            }
            else if (B != null && other.B != null && !B.Equals(other.B)) {
                return false;
            }
    
            // Value types can go down here.
            return someint.Equals(other.someint);
        }
    }
    
    class SubClassA {
        // some properties
    }
    
    class SubClassB {
        // some properties
    }
    
2

There are 2 best solutions below

2
shingo On

You don't need to reinvent the wheel. .NET has an EqualityComparer<T>.Default property that can handle most of equality comparison situations (including yours). Read the remark section for more details.

EqualityComparer<SubClassA>.Default.Equals(A, other.A);

Note, please read this article: System.Object.Equals method if you want to override Equals. In summary, you'd better override the GetHashCode method and implement the IEquatable<T> interface too.

0
Mayur Ekbote On

If the class/subclass is made up of only POCO or serializable objects, then serialize and compare the strings. Any other solution would require you to override Equals() and GetHashCode(). It is not worth the pain. Rather, create a specific method (say, "ValueEquals()") that compares specific members of the two objects.