Reputation: 42260
Whenever I write a new class
or struct
that is likely to hold some data, that may need to be compared, I always implement IEquatable<T>
as this provides the class/struct
with a 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;
}
}
As well as providing an implementation for .Equals(Radius other)
, I should really override the default implementation too (.Equals(object obj)
)
I have two options here, and my question is, which of these implementations is better?
Option 1 is to use casting:
public override bool Equals(object obj)
{
return this.Equals((Radius)obj);
}
Option 2 is to use the "as" keyword:
public override bool Equals(object obj)
{
return this.Equals(obj as Radius);
}
My reason for asking this is, using casting will throw an exception if obj
cannot be cast to Radius
, whereas as
will resolve to null
if it cannot be cast, therefore it just checks this
against null
, without throwing an exception; So is it better to throw an exception, or to just return false
?
EDIT: As it has been pointed out by quite a few fellow SO'ers, structs cannot be null, therefore the second option does not apply for a struct. Therefore another question springs to mind: Should the overridden implementation of .Equals(object obj)
be identical for structs and classes?
Upvotes: 4
Views: 4652
Reputation: 45101
As @SLaks already mentioned Equals()
should never throw.
In this special case i think a usage of the is
operator combined with a cast should help you out:
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.
}
Upvotes: 5
Reputation: 887433
The Equals()
method must never throw an exception.
An object of a different type is merely unequal.
Quoting the documentation:
Implementations of Equals must 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.
Upvotes: 7
Reputation: 178
My personal opinion would be to use the second option, or even check before hand if the object is a "Radius" and then return false so that the intent is more clear
Upvotes: -1