IEquatable <T> - best practice of overriding for .Equals (obj object) in C #
Whenever I write a new class or struct that may contain some data that may need to be compared, I always implement IEquatable<T> as it provides the class/struct strongly typed .Equals(T other) method.
Example:
public struct Radius : IEquatable<Radius> { public Int32 TopLeft { get; set; } public Int32 TopRight { get; set; } public Int32 BottomLeft { get; set; } public Int32 BottomRight { get; set; } public bool Equals(Radius other) { return this.TopLeft == other.TopLeft && this.TopRight == other.TopRight && this.BottomLeft == other.BottomLeft && this.BottomRight == other.BottomRight; } } Besides providing an implementation for .Equals(Radius other) , I have to really override the default implementation ( .Equals(object obj) )
I have two options, and my question is: which of these implementations is better?
Option 1 - use casting:
public override bool Equals(object obj) { return this.Equals((Radius)obj); } Option 2 - use the keyword "how":
public override bool Equals(object obj) { return this.Equals(obj as Radius); } My reason to ask for this is that using casting throws an exception if obj cannot be added to Radius , while as will be allowed to null if it cannot be distinguished, so it just checks this against null without throwing an exception; So is it better to throw an exception or just return false ?
EDIT: as many other SO'ers noted, structures cannot be null, so the second option does not apply to structures. Therefore, another question arises: should the overridden implementation of .Equals(object obj) be the same for structures and classes?
The Equals() method should never throw an exception .
An object of a different type is simply unequal.
Documentation citation:
Peer implementations should not throw exceptions; they should always return a value. For example, if obj is null, the Equals method should return false instead of throwing an ArgumentNullException.
As already mentioned, @SLaks Equals() should never rush.
In this special case, I think that using the is operator in conjunction with cast should help you:
public override bool Equals(object obj) { if(obj is Radius) return Equals((Radius)obj); return false; } In cases where you have a class , you should simply use the as operator:
public override bool Equals(object obj) { return Equals(obj as MyObj); } public bool Equals(MyObj obj) { if(ReferenceEquals(obj, null)) return false; // ToDo: further checks for equality. }