I'm trying to implement the IEquatable<T> interface and == operator. The implementation below triggers a NullReferenceException when I try to use the == operator despite the fact that both operands are non-null. I've added comments to the minimum example code to show exactly where the exception occurs. What am I doing wrong?
using System;
namespace scratchpad
{
class TestClass : IEquatable<TestClass>
{
public int data;
public TestClass(int d)
{
this.data = d;
}
public bool Equals(TestClass other)
{
if (other == null)
return false;
else
return this.data == other.data;
}
public override bool Equals(object other)
{
if (other is TestClass)
return this.Equals((TestClass)other);
else //Includes null
return false;
}
public override int GetHashCode()
{
return this.data;
}
public static bool operator ==(TestClass left, TestClass right)
{
return left.Equals(right); //This line triggers the NullReferenceException
}
public static bool operator !=(TestClass left, TestClass right)
{
return !left.Equals(right);
}
}
class Program
{
static void Main(string[] args)
{
TestClass tc1 = new TestClass(10);
TestClass tc2 = new TestClass(10);
Console.WriteLine("tc1="+tc1.data); //Prints "tc1.data=10" fine
Console.WriteLine("tc1="+tc1.data); //Prints "tc2.data=10" fine
bool isEqual = tc1 == tc2; //NullReferenceException occur here
Console.WriteLine("isEqual="+isEqual); //Never gets to here
}
}
}
Edit (to clarify question in response to duplicates question flags):
I am not asking what a NullReferenceException is (I understand that) and I am not interested in ReferenceEquals as I need to equate the object's values.
The line other == null in Equals(TestClass) calls the equality operator, which calls Equals(TestClass) -- an infinite loop. On the second round, other is null, which leads to a NullReferenceException when you pass that to the equality operator as the left parameter.
You should use ReferenceEquals(other, null) or other is null instead.
Actually, your overloaded equality operator is hit three times:
First, when called from Program.Main(string[]) with the line tc1 == tc2, where left=tc1 and right=tc2, which then calls TestClass.Equals(TestClass) where other=tc2.
From there, other == null now calls your overloaded equality operator a second time, where left=tc2 and right=null.
Now, TestClass.Equals(TestClass) is called also a second time, where other=null.
And finally, other == null calls your overloaded equality operator for a third time, where both left=null and right=null. This now eventually causes the System.NullReferenceException because left was null.
To fix this coding error, replace other == null with other is null in TestClass.Equals(TestClass):
public bool Equals(TestClass other)
{
if (other is null)
return false;
else
return data == other.data;
}
Alternatively, as conditional expression (using expression body):
public bool Equals(TestClass other) => !(other is null) && data == other.data;
Related
I recently came about this problem. I have a base Stamp class. Then I made two inherited classes OwnedStamp and AuctionStamp. I overrided the Equals and GetHashCode method in Stamp class like this:
public override bool Equals(object obj)
{
if(obj == null || this.GetType().Equals(obj.GetType()))
{
return false;
}
else
{
Stamp stamp = obj as Stamp;
return this.Title == stamp.Title;
}
}
public override int GetHashCode()
{
return Title.GetHashCode();
}
I also have overloaded these operators in the same class:
public static bool operator ==(Stamp lhs, Stamp rhs)
{
return lhs.Equals(rhs);
}
public static bool operator !=(Stamp lhs, Stamp rhs)
{
return !lhs.Equals(rhs);
}
Then I have this scenario:
OwnedStamp checkStamp = check.GetStampByTitle(stampTitle);
if(checkStamp != null && checkStamp.Price <= toCompare.Price)
{
picked.Add(check);
}
The checkStamp is not null and it holds the correct informtaion I need, but when i check for the equality for null it throws me the exception. I have other lines with code where I check for equality between two stamps of any type. I have tried couple of different Equals method realizations. The problem consists. I have red that checking equality in base class even if we pass child class to the method shouldn't be a problem. Any help would be apreciated!
I have created a custom abstract class, which in turn of course derived classes were also created.
public abstract class AbstractBaseClass
...
public class ChildClass1 : AbstractBaseClass
...
Now, whenever I declare for example AbstractBaseClass baseClass = null, and wherever null checks follow after this initialization, it always fails.
if (baseClass == null)
{
// this block is never reached - condition always evaluates to false
// let's say AbstractBaseClass baseClass = null is at line 10
// even if this condition is at line 11, condition still fails
}
Reason why there is a null check is because there are multiple derived classes, and on some process, I determine which type would it be (e.g. using switch cases). And of course there are invalid cases, in which I expect that the value would be the initialized null.
This is really weird, and I really am expecting that null check would evaluate to true.
What could be the possible causes why this happens (so that I can add more sample code depending on the info as the whole relevant code is quite big), and how should one fix this? Thank you.
EDIT:
Also, debugger value is null.
Oh that's right, as #taffer mentioned, == is overloaded for AbstractBaseClass. Here is that part and other relevant code:
protected bool Equals(AbstractBaseClass other)
{
return Equals(this.SomeUniqueProperty, other.SomeUniqueProperty);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
{
return false;
}
if (ReferenceEquals(this, obj))
{
return true;
}
return obj.GetType() == this.GetType() && this.Equals((AbstractBaseClass)obj);
}
public override int GetHashCode()
{
return (this.SomeUniqueProperty != null ? this.SomeUniqueProperty.GetHashCode() : 0);
}
public static bool operator ==(AbstractBaseClass a, AbstractBaseClass b)
{
if (ReferenceEquals(null, a))
{
return false;
}
return !ReferenceEquals(null, b) && a.Equals(b);
}
public static bool operator !=(AbstractBaseClass a, AbstractBaseClass b)
{
return !(a == b);
}
Your == overload is wrong, as you are returning false if a is null, ignoring the fact that b could also be null.
What you need to do is return true if both are null, or if a equals b:
public static bool operator ==(AbstractBaseClass a, AbstractBaseClass b)
{
var isANull = ReferenceEquals(null, a);
var isBNull = ReferenceEquals(null, b)
return (isANull && isBNull) || a?.Equals(b) ?? false;
}
Note: In case a is null but b is not, the .? operator will return null, and the ?? operator will return false.
As RufusL wrote in the comments, there's a shorter eqiuvalent code to get the same results:
public static bool operator ==(AbstractBaseClass a, AbstractBaseClass b)
{
return a?.Equals(b) ?? ReferenceEquals(null, b);
}
if a is null, return true if b is also null. if a is not null, return the result of a.Equals(b).
In case a is not null but b is, your Equals method should return false:
protected bool Equals(AbstractBaseClass other)
{
return other != null
? Equals(this.SomeUniqueProperty, other.SomeUniqueProperty)
: false;
}
I've been debugging an issue for quite some time and realize that it was coming from the usage of an == on a object where I should have used the object.Equals()
In order to prevent such issue, would like that the == operator calls the Object.Equals() that I have overridden.
Is that possible? The following code runs into a Stack-overflow exception...
public static bool operator ==(Portfolio a, Portfolio b)
{
return a != null && a.Equals(b);
}
public static bool operator !=(Portfolio a, Portfolio b)
{
return a != null && !a.Equals(b);
}
Thanks!
You're recursively calling the != operator from your != operator, hence the stack overflow. Use ReferenceEquals instead:
public static bool operator !=(Portfolio a, Portfolio b)
{
return !object.ReferenceEquals(a, null) && !a.Equals(b);
}
That said, this code is flawed because it'll return false if a is null and b isn't. You should check both objects for null:
public static bool operator !=(Portfolio a, Portfolio b)
{
if (object.ReferenceEquals(a, null))
{
return !object.ReferenceEquals(b, null);
}
return !a.Equals(b);
}
I have a complex type called "HalfDay" which is a combination of a DateTime and an Enum value to represent either AM/PM.
public class HalfDay
{
private DateTime _Date;
public DateTime Date { get { return _Date; } set { _Date = value.Date; } }
private DayHalf _Half;
public DayHalf Half { get { return _Half; } set { _Half = value; } }
}
I am trying to write a set of overloaded operators to compare two HalfDays.
public static bool operator <(HalfDay halfday1, HalfDay halfday2)
{
if (halfday1.Date.Date < halfday2.Date.Date) return true;
if (halfday1.Date == halfday2.Date && halfday1.Half < halfday2.Half) return true;
return false;
}
public static bool operator >(HalfDay halfday1, HalfDay halfday2)
{
if (halfday1.Date.Date > halfday2.Date.Date) return true;
if (halfday1.Date == halfday2.Date && halfday1.Half > halfday2.Half) return true;
return false;
}
public static bool operator ==(HalfDay halfday1, HalfDay halfday2)
{
if (halfday1 == null && halfday2 == null) return true;
if (halfday1 == null || halfday2 == null) return false;
return halfday1.Date.Date == halfday2.Date.Date && halfday1.Half == halfday2.Half;
}
public static bool operator !=(HalfDay halfday1, HalfDay halfday2)
{
if (halfday1 == null && halfday2 == null) return false;
if (halfday1 == null || halfday2 == null) return true;
return !(halfday1 == halfday2);
}
In true newbie style (I've never written operators before) I've used the == comparison to compare a HalfDay with null. The result is, of course, a stack overflow as my operator code gets called recursively.
I think I need to check for null in my operators to correctly return false (or true) for comparisons being made where either of the arguments is null. I've clearly misunderstood something fundamental about OOP though - any pointers on how I should correctly write these operators?
See: Guidelines for Overloading Equals() and Operator == (C# Programming Guide)
A common error in overloads of operator == is to use (a == b), (a ==
null), or (b == null) to check for reference equality. This instead
results in a call to the overloaded operator ==, causing an infinite
loop. Use ReferenceEquals or cast the type to Object, to avoid the
loop.
For comparing it against null you can do (Example code from documentation):
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
{
return false;
}
Also read:
By default, the operator == tests for reference equality by determining if two references indicate the same object, so reference types do not need to implement operator == in order to gain this functionality. When a type is immutable, meaning the data contained in the instance cannot be changed, overloading operator == to compare value equality instead of reference equality can be useful because, as immutable objects, they can be considered the same as long as they have the same value. Overriding operator == in non-immutable types is not recommended.
As others already mentioned, when you want to check for reference equality, bypassing any == or Equals(), use object.ReferenceEquals().
Also, when overloading ==, you should also override Equals() (and implement IEquatable<T>). When you do that, you can then take advantage of the fact that object.Equals(object, object) makes all the null checks and then invokes Equals(). So, your code could look like this:
public bool Equals(HalfDay other)
{
if (object.ReferenceEquals(other, null))
return false;
if (object.ReferenceEquals(other, this))
return true;
return this.Date.Date == other.Date.Date && this.Half == other.Half;
}
public int GetHashCode()
{
// TODO
}
public override bool Equals(object other)
{
return Equals(other as HalfDay);
}
public static bool operator ==(HalfDay halfday1, HalfDay halfday2)
{
return object.Equals(halfday1, halfday2);
}
public static bool operator !=(HalfDay halfday1, HalfDay halfday2)
{
return !(halfday1 == halfday2);
}
Also, keep in mind what happens when there is a type that inherits from HalfDay. If you don't want to deal with that, make HalfDay sealed.
But, considering that you're also implementing comparison operators, you should considering unifying those too. For an example (with detailed explanation), see Eric Lippert's Math from scratch, part six: comparisons (you don't need to read the rest of the series).
Try using Object.ReferenceEquals instead:
public static bool operator ==(HalfDay halfday1, HalfDay halfday2)
{
if (Object.ReferenceEquals(halfday1, halfday2)) return true;
if (Object.ReferenceEquals(halfday1, null) || Object.ReferenceEquals(halfday2, null)) return false;
return halfday1.Date.Date == halfday2.Date.Date && halfday1.Half == halfday2.Half;
}
I have implemented the IEquatable interface in a class with the following code.
public bool Equals(ClauseBE other)
{
if (this._id == other._id)
{
return true;
}
return false;
}
public override bool Equals(Object obj)
{
if (obj == null)
{
return base.Equals(obj);
}
if (!(obj is ClauseBE))
{
throw new InvalidCastException("The 'obj' argument is not a ClauseBE object.");
}
return Equals(obj as ClauseBE);
}
public override int GetHashCode()
{
return this._id.GetHashCode();
}
public static bool operator ==(ClauseBE a, ClauseBE b)
{
// cast to object so we call the overloaded Equals function which appropriately checks when b is null.
return a.Equals(b as object);
}
public static bool operator !=(ClauseBE a, ClauseBE b)
{
// cast to object so we call the overloaded Equals function which appropriately checks when b is null.
return !a.Equals(b as object);
}
This code work very well for most all cases. However, the following check throws an exception in the equality operator overload method because a is null and therefore does not have a Equals method.
if(this.Clause != null)
{
}
What is the standard way to solve this issue?
EDIT
I have gone to this, but it seems pretty cumbersome. I was hoping there was a more elegant way to accomplish this.
public static bool operator ==(ClauseBE a, ClauseBE b)
{
if (a as object == null && b as object == null)
{
return true;
}
if ((a as object == null && b as object != null)
|| (b as object == null && a as object != null))
{
return false;
}
// cast to object so we call the overloaded Equals function which appropriately checks when b is null.
return a.Equals(b as object);
}
public static bool operator !=(ClauseBE a, ClauseBE b)
{
if (a as object == null && b as object == null)
{
return false;
}
if((a as object == null && b as object != null)
|| (b as object == null && a as object != null))
{
return true;
}
// cast to object so we call the overloaded Equals function which appropriately checks when b is null.
return !a.Equals(b as object);
}
Solution
Thanks all. I got a lot of good tips from everyone, I really appreciate it. This is what I finally settled on, it's a lot more elegant than what I had started with. All code is the same except operator overloads.
public static bool operator ==(ClauseBE a, ClauseBE b)
{
if (ReferenceEquals(a, null) && ReferenceEquals(b, null))
{
return true;
}
if (ReferenceEquals(a, null) || ReferenceEquals(b, null))
{
return false;
}
return a.Equals(b);
}
public static bool operator !=(ClauseBE a, ClauseBE b)
{
return !(a == b);
}
I've always found it easier to write the static operator with null handling, and have the Equals override call the overloaded operator with "this" as one of the parameters.
From Guidelines for Overloading Equals() and Operator == (C# Programming Guide)
//add this code to class ThreeDPoint as defined previously
//
public static bool operator ==(ThreeDPoint a, ThreeDPoint b)
{
// If both are null, or both are same instance, return true.
if (System.Object.ReferenceEquals(a, b))
{
return true;
}
// If one is null, but not both, return false.
if (((object)a == null) || ((object)b == null))
{
return false;
}
// Return true if the fields match:
return a.x == b.x && a.y == b.y && a.z == b.z;
}
public static bool operator !=(ThreeDPoint a, ThreeDPoint b)
{
return !(a == b);
}
This is how ReSharper creates equality operators and implements IEquatable<T>, which I trust blindly, of course ;-)
public class ClauseBE : IEquatable<ClauseBE>
{
private int _id;
public bool Equals(ClauseBE other)
{
if (ReferenceEquals(null, other))
return false;
if (ReferenceEquals(this, other))
return true;
return other._id == this._id;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
return false;
if (ReferenceEquals(this, obj))
return true;
if (obj.GetType() != typeof(ClauseBE))
return false;
return Equals((ClauseBE)obj);
}
public override int GetHashCode()
{
return this._id.GetHashCode();
}
public static bool operator ==(ClauseBE left, ClauseBE right)
{
return Equals(left, right);
}
public static bool operator !=(ClauseBE left, ClauseBE right)
{
return !Equals(left, right);
}
}
Check for null and return false. Equals should always be false if one of the operands is null;
I think this is a bit less cumbersome than casting to Object before checking for null:
ReferenceEquals(a, null)
Other answers give good solutions to the general problem.
However, your own code can be simplified into a relatively simple solution ...
Firstly, at the start of your == operator you have this:
// First test
if (a as object == null && b as object == null)
{
return true;
}
This qualifies as "working too hard".
If ClauseBE is a reference type, then you only need to compare with null - the "as object" is redundant; equally, if ClauseBE is a value type, then it can never be null.
Assuming that ClauseBE is a reference type (the most likely case), then you can simplify to this - note that we use Object.Equals() to avoid infinite recursion and a stack blowout.
// First test
if (Object.Equals(a, null) && Object.Equals(b, null))
{
return true;
}
One useful shortcut is to use Object.ReferenceEquals() - which handles nulls for you.
So you could write this instead:
// First test
if (Object.ReferenceEquals(a, b))
{
return true;
}
with the bonus that this also handles the case where a and b are the same exact object.
Once you get past the Object.ReferenceEquals() test, you know that a and b are different.
So your next test:
// Second test
if ((a as object == null && b as object != null)
|| (b as object == null && a as object != null))
{
return false;
}
can be simplified - since you know that if a is null, b cannot be null, and so on.
// Second test
if (Object.Equals(a, null) || Object.Equals(b, null))
{
return false;
}
If this test fails, then you know that a and b are different, and that neither is null. A good time to call your overridden Equals().
// Use the implementation of Equals() for the rest
return a.Equals(b as object);
public class Foo : IEquatable<Foo>
{
public Int32 Id { get; set; }
public override Int32 GetHashCode()
{
return this.Id.GetHashCode();
}
public override Boolean Equals(Object obj)
{
return !Object.ReferenceEquals(obj as Foo, null)
&& (this.Id == ((Foo)obj).Id);
// Alternative casting to Object to use == operator.
return ((Object)(obj as Foo) != null) && (this.Id == ((Foo)obj).Id);
}
public static Boolean operator ==(Foo a, Foo b)
{
return Object.Equals(a, b);
}
public static Boolean operator !=(Foo a, Foo b)
{
return !Object.Equals(a, b);
}
public Boolean Equals(Foo other)
{
return Object.Equals(this, other);
}
}
I have used the following approach and it seemed to work well for me. Infact, Resharper suggests this approach.
public bool Equals(Foo pFoo)
{
if (pFoo == null)
return false;
return (pFoo.Id == Id);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(obj, this))
return true;
return Equals(obj as Foo);
}
I prefer to perform all the comparison logic in the Equals(T) method, and leave the "if this or that is null, else ..." in operator overloads to the framework.
The only tricky thing about overriding operator overloads is that you can no longer use those operators in your Equals implementation, for example to compare with null. Instead, object.ReferenceEquals can be used to achieve the same effect.
Following the TwoDPoint example in the MSDN Guidelines for Overriding Equals() and Operator == article, this is the pattern I generate when implementing value equality for types:
public override bool Equals( object obj ) {
// Note: For value types, would use:
// return obj is TwoDPoint && this.Equals( (TwoDPoint)obj );
return this.Equals( obj as TwoDPoint );
}
public bool Equals( TwoDPoint other ) {
// Note: null check not needed for value types.
return !object.ReferenceEquals( other, null )
&& EqualityComparer<int>.Default.Equals( this.X, other.X )
&& EqualityComparer<int>.Default.Equals( this.Y, other.Y );
}
public static bool operator ==( TwoDPoint left, TwoDPoint right ) {
// System.Collections.Generic.EqualityComparer<T> will perform the null checks
// on the operands, and will call the Equals overload if necessary.
return EqualityComparer<TwoDPoint>.Default.Equals( left, right );
}
public static bool operator !=( TwoDPoint left, TwoDPoint right ) {
return !EqualityComparer<TwoDPoint>.Default.Equals( left, right );
}
The form above is the safest implementation, as it simply forwards the field equality checks to the framework and requires no knowledge of whether the fields overload the equality operators. It is perfectly fine to simplify this where you know the overload exists:
public bool Equals( TwoDPoint other ) {
return !object.ReferenceEquals( other, null )
&& this.X == other.X
&& this.Y == other.Y;
}
You can also replace the EqualityComparer<T> calls in the operator overloads with calls to the static object.Equals method when comparing reference types, or when boxing value types does not matter:
public static bool operator ==( TwoDPoint left, TwoDPoint right ) {
return object.Equals( left, right );
}
public static bool operator !=( TwoDPoint left, TwoDPoint right ) {
return !object.Equals( left, right );
}
See also What is the best algorithm for an overridden GetHashCode? for implementing GetHashCode.