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!
Related
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'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;
Why does this program print "not added" while I think it should print "added"?
using System;
using System.Collections.Generic;
class Element
{
public int id;
public Element(int id)
{
this.id = id;
}
public static implicit operator Element(int d)
{
Element ret = new Element(d);
return ret;
}
public static bool operator ==(Element e1, Element e2)
{
return (e1.id == e2.id);
}
public static bool operator !=(Element e1, Element e2)
{
return !(e1.id == e2.id);
}
}
class MainClass
{
public static void Main(string[] args)
{
List<Element> element = new List<Element>();
element.Add(2);
if(element.Contains(2))
Console.WriteLine("added");
else
Console.WriteLine("not added");
}
}
The Contains method does not use the == operator. What is the problem?
The Contains method does not use the == operator
No - it uses Equals, which you haven't overridden... so you're getting the default behaviour of Equals, which is to check for reference identity instead. You should override Equals(object) and GetHashCode to be consistent with each other - and for sanity's sake, consistent with your == overload too.
I'd also recommend implementing IEquatable<Element>, which List<Element> will use in preference to Equals(object), as EqualityComparer<T>.Default picks it up appropriately.
Oh, and your operator overloads should handle null references, too.
I'd also strongly recommend using private fields instead of public ones, and making your type immutable - seal it and make id readonly. Implementing equality for mutable types can lead to odd situations. For example:
Dictionary<Element, string> dictionary = new Dictionary<Element, string>();
Element x = new Element(10);
dictionary[x] = "foo";
x.id = 100;
Console.WriteLine(dictionary[x]); // No such element!
This would happen because the hash code would change (at least under most implementations), so the hash table underlying the dictionary wouldn't be able to find even a reference to the same object that's already in there.
So your class would look something like this:
internal sealed class Element : IEquatable<Element>
{
private readonly int id;
public int Id { get { return id; } }
public Element(int id)
{
this.id = id;
}
public static implicit operator Element(int d)
{
return new Element(d);
}
public static bool operator ==(Element e1, Element e2)
{
if (object.ReferenceEquals(e1, e2))
{
return true;
}
if (object.ReferenceEquals(e1, null) ||
object.ReferenceEquals(e2, null))
{
return false;
}
return e1.id == e2.id;
}
public static bool operator !=(Element e1, Element e2)
{
// Delegate...
return !(e1 == e2);
}
public bool Equals(Element other)
{
return this == other;
}
public override int GetHashCode()
{
return id;
}
public override bool Equals(object obj)
{
// Delegate...
return Equals(obj as Element);
}
}
(I'm not sure about the merit of the implicit conversion, by the way - I typically stay away from those, myself.)
The Contains method does not use the == operator. What is the problem?
That is correct.
This method [Contains] determines equality by using the default equality comparer, as defined by the object's implementation of the IEquatable.Equals method for T (the type of values in the list).
http://msdn.microsoft.com/en-us/library/bhkz42b3(v=vs.110).aspx
You need to override Equals() as well. Note when you overload Equals(), it is almost always correct to also override GetHashCode().
Override Equals and GetHashCode like:
class Element
{
public int id;
protected bool Equals(Element other)
{
return id == other.id;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Element) obj);
}
public override int GetHashCode()
{
return id; //or id.GetHashCode();
}
//..... rest of the class
See: List<T>.Contains Method
This method determines equality by using the default equality
comparer, as defined by the object's implementation of the
IEquatable<T>.Equals method for T (the type of values in the list).
Why does this program print "not added" while I think it should print "added"?
using System;
using System.Collections.Generic;
class Element
{
public int id;
public Element(int id)
{
this.id = id;
}
public static implicit operator Element(int d)
{
Element ret = new Element(d);
return ret;
}
public static bool operator ==(Element e1, Element e2)
{
return (e1.id == e2.id);
}
public static bool operator !=(Element e1, Element e2)
{
return !(e1.id == e2.id);
}
}
class MainClass
{
public static void Main(string[] args)
{
List<Element> element = new List<Element>();
element.Add(2);
if(element.Contains(2))
Console.WriteLine("added");
else
Console.WriteLine("not added");
}
}
The Contains method does not use the == operator. What is the problem?
The Contains method does not use the == operator
No - it uses Equals, which you haven't overridden... so you're getting the default behaviour of Equals, which is to check for reference identity instead. You should override Equals(object) and GetHashCode to be consistent with each other - and for sanity's sake, consistent with your == overload too.
I'd also recommend implementing IEquatable<Element>, which List<Element> will use in preference to Equals(object), as EqualityComparer<T>.Default picks it up appropriately.
Oh, and your operator overloads should handle null references, too.
I'd also strongly recommend using private fields instead of public ones, and making your type immutable - seal it and make id readonly. Implementing equality for mutable types can lead to odd situations. For example:
Dictionary<Element, string> dictionary = new Dictionary<Element, string>();
Element x = new Element(10);
dictionary[x] = "foo";
x.id = 100;
Console.WriteLine(dictionary[x]); // No such element!
This would happen because the hash code would change (at least under most implementations), so the hash table underlying the dictionary wouldn't be able to find even a reference to the same object that's already in there.
So your class would look something like this:
internal sealed class Element : IEquatable<Element>
{
private readonly int id;
public int Id { get { return id; } }
public Element(int id)
{
this.id = id;
}
public static implicit operator Element(int d)
{
return new Element(d);
}
public static bool operator ==(Element e1, Element e2)
{
if (object.ReferenceEquals(e1, e2))
{
return true;
}
if (object.ReferenceEquals(e1, null) ||
object.ReferenceEquals(e2, null))
{
return false;
}
return e1.id == e2.id;
}
public static bool operator !=(Element e1, Element e2)
{
// Delegate...
return !(e1 == e2);
}
public bool Equals(Element other)
{
return this == other;
}
public override int GetHashCode()
{
return id;
}
public override bool Equals(object obj)
{
// Delegate...
return Equals(obj as Element);
}
}
(I'm not sure about the merit of the implicit conversion, by the way - I typically stay away from those, myself.)
The Contains method does not use the == operator. What is the problem?
That is correct.
This method [Contains] determines equality by using the default equality comparer, as defined by the object's implementation of the IEquatable.Equals method for T (the type of values in the list).
http://msdn.microsoft.com/en-us/library/bhkz42b3(v=vs.110).aspx
You need to override Equals() as well. Note when you overload Equals(), it is almost always correct to also override GetHashCode().
Override Equals and GetHashCode like:
class Element
{
public int id;
protected bool Equals(Element other)
{
return id == other.id;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((Element) obj);
}
public override int GetHashCode()
{
return id; //or id.GetHashCode();
}
//..... rest of the class
See: List<T>.Contains Method
This method determines equality by using the default equality
comparer, as defined by the object's implementation of the
IEquatable<T>.Equals method for T (the type of values in the list).
I have had a few problems getting this right, so I wanted to ask if anyone has any feedback on whether this is an efficient way to implement the Equals method and equality/inequality operators for a custom immutable class. These operators are called very frequently by my program, so I want to make sure I get them right.
class MyObj
{
public static bool operator ==(MyObj a, MyObj b)
{
if (!object.ReferenceEquals(a, null))
return a.Equals(b);
else if (!object.ReferenceEquals(b, null))
return b.Equals(a);
else
// both are null
return true;
}
public static bool operator !=(MyObj a, MyObj b)
{
if (!object.ReferenceEquals(a, null))
return !a.Equals(b);
else if (!object.ReferenceEquals(b, null))
return !b.Equals(a);
else
// both are null
return false
}
public override bool Equals(object obj)
{
return this.Equals(obj as MyObj);
}
public bool Equals(MyObj obj)
{
if (object.ReferenceEquals(obj, null))
return false;
else
return (obj.FieldOne == this.FieldOne &&
obj.FieldTwo == this.FieldTwo && ...);
}
}
I use the following code snippet for reference types, which has less duplication and feels cleaner, in my opinion. Having a static "Equals" method allows .NET languages without operator overloading to compare your instances without having to test for null before calling the instance method. If you're implementing equality operators, it might also be best to make your class immutable, if you can.
class Foo : IEquatable<Foo>
{
public override bool Equals(object obj)
{
return Equals(obj as Foo);
}
public bool Equals(Foo other)
{
if (object.ReferenceEquals(other, null)) return false;
// Optional early out
if (object.ReferenceEquals(this, other)) return true;
// Compare fields here
}
public static bool Equals(Foo a, Foo b)
{
if (ReferenceEquals(a, null)) return ReferenceEquals(b, null);
return a.Equals(b);
}
public static bool operator ==(Foo a, Foo b)
{
return Equals(a, b);
}
public static bool operator !=(Foo a, Foo b)
{
return !Equals(a, b);
}
}
Some things I'm noticing:
Because you're overriding Equals, you should also override GetHashCode.
Since your Equals(MyObj) method is a valid implementation for the entire IEquatable<MyObj> interface, MyObj should indeed implement that interface. This will also allow Dictionary<> and such to directly take advantage of your Equals(MyObj) method, instead of going through Equals(object).
Also I completely agree with Trillian's alternative implementation, except I would've implemented a != b directly as !(a == b) instead of !Equals(a, b). (Trivial difference of course.)
Basically yes, but there is an error to correct.
The Equals(object) method calls itself instead of calling the Equals(MyObj) method, causing an eternal loop. It should be:
public override bool Equals(object obj) {
MyObj other = obj as MyObj;
return this.Equals(other);
}
or simply:
public override bool Equals(object obj) {
return this.Equals(obj as MyObj);
}
Also, you can simplify the inequality operator to:
public static bool operator !=(MyObj a, MyObj b) {
return !(a == b);
}
If you're looking for efficiency, I recommend using this instead of object.ReferenceEquals(foo, null):
(object)foo == null
This is effectively equivalent but avoids a function call.
I also like to implement IEquatable<T> in all my types that override Equals. For reference types, I then forward Equals(object) to Equals(Foo).
public override bool Equals(object other){return Equals(other as Foo);}
The operator overloads can be simplified as so:
public static bool operator==(Foo a, Foo b){
if((object)a == null)
return (object)b == null;
return a.Equals(b);
}
public static bool operator!=(Foo a, Foo b){
return !(a == b);
}
If absolute efficiency is needed, though, it may be worth a little duplication of code in these functions to avoid the extra function calls, but unlike using (object)foo == null instead of object.ReferenceEquals(foo, null), avoiding the function call requires extra code to maintain, so the small gain may not be worth it.
I prefer to leave all the "if this is null then do that else..." logic to the framework:
class MyObj : IEquatable<MyObj> {
public static bool operator ==( MyObj left, MyObj right ) {
return EqualityComparer<MyObj>.Default.Equals( left, right );
}
public static bool operator !=( MyObj left, MyObj right ) {
return !EqualityComparer<MyObj>.Default.Equals( left, right );
}
public override bool Equals( object obj ) {
return this.Equals( obj as MyObj );
}
public bool Equals( MyObj other ) {
return !object.ReferenceEquals( other, null )
&& obj.FieldOne == this.FieldOne
&& obj.FieldTwo == this.FieldTwo
&& ...
;
}
...
}
See also What is the best algorithm for an overridden GetHashCode? for implementing GetHashCode.