Question

As my (unit-)test coverage is still quite low, unfortunately, I have to find lots of errors the hard way. Therefore, during refactoring, I heavily rely on type checking of the C# compiler.

Today, I fixed a bug introduced during refactoring by missing a line with x.Equals(aThingWrappingOriginalThing). As it's bool Equals(object T), the compiler did not complain. However, 90% of the time I use Equals() directly (instead through the BCL), I intend to logically compare objects of the same type.

Now I'm wondering why I've never seen someone promoting a type-safe version of Equals() for such situations (in C#). Is there a best practice for this?

I'm tempted to use an extension method for those comparisions, like so:

public static bool SafeEquals<T>(this T a, T b)
{
    if (a == null) return b == null;
    return a.Equals(b);
}
public static bool SafeEquals<X>(this IEquatable<X> a, IEquatable<X> b)
{
    if (a == null) return b == null;
    return a.Equals(b);
}

Could these be optimized?

Here's the only blog post about the topic I found, for java: http://rickyclarkson.blogspot.com/2006/12/making-equalsobject-type-safe.html

Was it helpful?

Solution

You are looking for

EqualityComparer<T>.Default.Equals(x,y);

this supports IEquatable<T> (if implemented), else uses the potentially-boxing Equals(object); it supports classes and structs, with expected null-behaviour for both, including support for Nullable<T> (without boxing).

OTHER TIPS

What I see looks good to me.

My 2 cents: I think it would be simpler to skip the null checks, and use this:

public static bool SafeEquals<T>(this T a, T b)
{
    return object.Equals(a, b);
}

There are very few cases in which that would deviate from intended behaviour. One of them is when Equals returns false when both objects are the same object (which should never happen anyway).

For reference, here is the decompiled object.Equals, so you can see for yourself what happens.

public static bool Equals(object objA, object objB)
{
    return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB)));
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top