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?

+4
source share
3 answers

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.

+7
source

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. } 
+2
source

My personal opinion would be to use the second option or even check before hand if the object is "Radius" and then returns false so that the intention is more clear.

-one
source

Source: https://habr.com/ru/post/1495770/


All Articles