(C#) Problems when overloading the == operator [duplicate] - c#

This question already has answers here:
How do I check for nulls in an '==' operator overload without infinite recursion?
(13 answers)
Closed 9 years ago.
I overloaded the == operator on my class as follows:
public static bool operator ==(Table pt1, Table pt2) {
return Compare(pt1, pt2) == 0 && pt1.TableName == pt2.TableName;
}
Compare will work just as the strcmp does in c++, returning an integer. Problem is that if I do an if (MY_CLASS == null), it will call my == operator, and thus my Compare function. What is the alternatiev? to put an check on pt1 and pt2 to see if they are null? Or just in pt2?

You should checkout Microsoft's guidelines for implementing the '==' operator and also for overriding 'Equals()'.
Adapting their example you'd want something like:
public static bool operator ==(Table a, Table 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 Compare(a, b) == 0 && a.TableName == b.TableName;
}

You will need the null checks to get the correct behaviour. The clearest way to add this check in my opinion is to call object.ReferenceEquals(x, null), since it is a straight non-polymorphic method call and presumably fairly efficient.

Just add this line to your operator:
if ((object)pt1 == null || (object)pt2 == null) return false;
The (object) cast is there to prevent recursion (from calling object.== instead of MY_CLASS.==.
Although I'm not sure of the conditions that should arise when comparing null to null.

I asked a similar question here. Have a look at it.
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)
{
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);
}

Related

The object is null, however checking if it's null returning false

I am suffering a weird problem in C# 4.5.
I have this in my model:
private DataMatrix<T> _matrix;
public DataMatrix<T> Matrix
{
get { return _matrix; }
set { _matrix = value; }
}
And I have a property which uses this:
public object SingleElement
{
get
{
if (Matrix == null) return String.Empty;
if (Matrix.ColumnCount >= 1 && Matrix.RowCount >= 1)
{
return Matrix[0, 0];
}
return null;
}
}
When I run it, before calling SingleElement, the Matrix property is null. But it doesn't return String.Empty, it goes to the second if-statement.
That's my Immediate window says:
I'm a bit confused. What did I do wrong?
This is a most likely a broken equality operator (==), which can be reproduced with the following code:
class Foo
{
public static bool operator == (Foo x, Foo y)
{
return false; // probably more complex stuff here in the real code
}
public static bool operator != (Foo x, Foo y)
{
return !(x == y);
}
static void Main()
{
Foo obj = null;
System.Diagnostics.Debugger.Break();
}
// note there are two compiler warnings here about GetHashCode/Equals;
// I am ignoring those for brevity
}
now at the breakpoint in the immediate window:
?obj
null
?(obj==null)
false
Two fixes:
preferred would be to fix the operator, perhaps adding before anything else:
if(ReferenceEquals(x,y)) return true;
if((object)x == null || (object)y == null) return false;
// the rest of the code...
alternative, if you can't edit that type, is to avoid using the operator; consider using ReferenceEquals explicitly in your code, or performing object-based null checks; for example:
if(ReferenceEquals(Matrix, null)) ...
or
if((object)Matrix == null) ...

When overloading the equality operator, what's the best way to handle null values? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I check for nulls in an ‘==’ operator overload without infinite recursion?
Say I have a type like this:
public class Effect
{
public static bool operator == ( Effect a, Effect b )
{
return a.Equals ( b );
}
public static bool operator != ( Effect a, Effect b )
{
return !a.Equals ( b );
}
public bool Equals ( Effect effect )
{
return this.TypeID.Equals ( effect.TypeID );
}
public override bool Equals ( object obj )
{
return this.TypeID.Equals ( ( ( Effect ) obj ).TypeID );
}
}
What's the most robust and cleanest way to handle null values?
I am not sure if I have to check for null for both the current instance (this) and the passed instance (effect/obj)? If I have null for the current instance (this), would the compiler still call effect.Equals or Object.Equals?
Also either way where should the null checks be done? I am assuming only inside the Equals methods, and not the equality operators (==, !=).
Firstly, this can never be null, at least not in code produced by the C# compiler.
Second, use the ReferenceEquals method to check for a null reference without possibly calling an overloaded version of == (or do ((object) sometypeinstance) == null).
Visual Studio has a snippet that provides a basic Equals() implementation for you. I'd follow that, unless you have a strong reason not to.
// override object.Equals
public override bool Equals(object obj)
{
//
// See the full list of guidelines at
// http://go.microsoft.com/fwlink/?LinkID=85237
// and also the guidance for operator== at
// http://go.microsoft.com/fwlink/?LinkId=85238
//
if (obj == null || GetType() != obj.GetType())
{
return false;
}
// TODO: write your implementation of Equals() here
throw new NotImplementedException();
return base.Equals(obj);
}
// override object.GetHashCode
public override int GetHashCode()
{
// TODO: write your implementation of GetHashCode() here
throw new NotImplementedException();
return base.GetHashCode();
}
How about
public static bool operator == ( Effect a, Effect b )
{
return object.Equals(a, b);
}
The default implementation of Object.Equals() does the null checking for you.
In case you're curious, here's how Object.Equals() does it (courtesy of .NET Reflector):
public static bool Equals(object objA, object objB)
{
return ((objA == objB) || (((objA != null) && (objB != null)) && objA.Equals(objB)));
}
It is necessary to check for nulls with every method that takes parameters making your class.
public class Effect
{
public static bool operator == ( Effect a, Effect b )
{
if (a == null) && (b == null) return true;
if (a == null) return false;
return a.Equals ( b );
}
public static bool operator != ( Effect a, Effect b )
{
return !(a == b);
}
public bool Equals ( Effect effect )
{
if (b == null) return false;
return this.TypeID.Equals ( effect.TypeID );
}
public override bool Equals ( object obj )
{
if (obj == null) return false;
return this.TypeID.Equals ( ( ( Effect ) obj ).TypeID );
}
}
Other things to look out for are GetHashCode which should be implemented if equality is being implemented and the fact that GetHashCode should only be implemented on immutable properties, if this object is going to be used in a dictionary or similar object that compares items using the hash code.
Yes, you should chech against null. Why are you afraid of that?
Remember that when you play around with equals, you probably also want to take a look at the hashcode method! Those two methods are intertwined.
Add this:
public static bool operator == ( Effect a, Effect b )
{
return a is Effect && b is Effect && a.TypeID.Equals (b.TypeID);
}
public static bool operator != ( Effect a, Effect b )
{
return !(a == b );
}
public bool Equals ( Effect effect )
{
return this == effect );
}
public override bool Equals ( object obj )
{
return obj is Effect && this == obj);
}
or instead of last put:
public override bool Equals ( object obj )
{
if (obj == null) throw new ArgumentNullException(
"obj", "obj is null");
if (!(obj is effect)) throw new ArgumentException(
"obj", "obj is not an effect");
return obj is Effect && this == obj);
}

Have I changed the intent of the overridden `==` operator?

The following overloaded ==operator is part of the Calender class in QL.net
public static bool operator ==(Calendar c1, Calendar c2)
{
return (c1.empty() && c2.empty())
|| (!c1.empty() && !c2.empty() && c1.name() == c2.name());
}
public bool empty() { return (object)calendar == null; }
When I try to access the SouthAfricanCalender property, I receive a System.NullReferenceException : Object reference not set to an instance of an object. which prompted me to dig into the source.
public SouthAfrica SouthAfricanCalender
{
get
{
if (_calender == null)
{
_calender = new SouthAfrica();
}
return _calender;
}
set
{
if (_calender == null)
{
_calender = value;
}
}
}
SouthAfrica _calender;
I have ammended the overload as follows based on the answer here
public static bool operator ==(Calendar c1, Calendar c2)
{
if ( object.ReferenceEquals(c1,c2)) return true;
if ((object)c1 == null || (object)c2 == null) return false;
return (c1.empty() && c2.empty())
|| (!c1.empty() && !c2.empty() && c1.name() == c2.name());
}
My question, have I changed the intent of the original code with my amendment?
Edit: any suggestions on how this can be cleaned up further?
No. You ensure that both are objects, and respond accordingly in the places that they aren't (assuming that ReferenceEquals can handle double null). Then you simply execute the same check. The whole .empty() thing is totally unnecessary, by the way, you already know that it's not null, just return the name comparison.
No, you haven't.
It still checks for equality.

overload == (and != , of course) operator, can I bypass == to determine whether the object is null

when I try to overload operator == and != in C#, and override Equal as recommended, I found I have no way to distinguish a normal object and null. For example, I defined a class Complex.
public static bool operator ==(Complex lhs, Complex rhs)
{
return lhs.Equals(rhs);
}
public static bool operator !=(Complex lhs, Complex rhs)
{
return !lhs.Equals(rhs);
}
public override bool Equals(object obj)
{
if (obj is Complex)
{
return (((Complex)obj).Real == this.Real &&
((Complex)obj).Imaginary == this.Imaginary);
}
else
{
return false;
}
}
But when I want to use
if (temp == null)
When temp is really null, some exception happens. And I can't use == to determine whether the lhs is null, which will cause infinite loop.
What should I do in this situation.
One way I can think of is to us some thing like Class.Equal(object, object) (if it exists) to bypass the == when I do the check.
What is the normal way to solve the problem?
Thank you.
You can use the following at the top of your Equals override:
if (Object.ReferenceEquals(obj, null))
return false;
The exception you are getting is probably a StackOverflowException because your == operator will cause infinite recursion.
EDIT:
If Complex is a struct you should not have any problems with NullReferenceExceptions. If Complex is a class you can change your implementation of the == and != operator overloads to avoid the exception (Laurent Etiemble already pointed this out in his answer):
public static bool operator ==(Complex lhs, Complex rhs)
{
return Equals(lhs, rhs);
}
public static bool operator !=(Complex lhs, Complex rhs)
{
return !Equals(lhs, rhs);
}
You should consider using the static Equals method in the operator overloads (which will call the instance Equals method):
public static bool operator ==(Complex lhs, Complex rhs)
{
return Equals(lhs, rhs);
}
public static bool operator !=(Complex lhs, Complex rhs)
{
return !Equals(lhs, rhs);
}
Note: You may also check for null in the Equals method.
You can also read the Object.Equals Topic on MSDN, which is a great source of samples.
public static bool operator ==(Complex lhs, Complex rhs)
{
if (Object.ReferenceEquals(lhs, null))
{
return Object.ReferenceEquals(rhs, null);
}
return lhs.Equals(rhs);
}
public static bool operator !=(Complex lhs, Complex rhs)
{
return !(lhs == rhs);
}
Poor man's unit test
Action<Complex, Complex> tester = (left, right) =>
{
Console.WriteLine(left == right);
Console.WriteLine(left != right);
Console.WriteLine(left == null);
Console.WriteLine(left != null);
Console.WriteLine("---");
};
tester(new Complex(), new Complex());
tester(null, new Complex());
tester(null, null);
tester(new Complex(), null);
I think you shoud test for null in the == operator implementation. Otherwise, when lhs is null, you'd call Complex(null).Equals (I don't know for C#, but in Java this would be a Nullpointer Exception)
To test for null, I suggest something like:
if (null == lhs && null == rhs) return true
else if (null == lhs) return false
else return lhs.Equals(rhs);
So Object.Equals will be called for all == comparisons above.
There is a better approach then using operators is and cast:
Complex c = obj as Complex;
return (c != null) && (c.Real == this.Real) && (c.Imaginary == this.Imaginary);
Here is a quick test concerning Equals operator override and comparing with null:
class Complex
{
public override bool Equals(object obj)
{
if (obj is Complex)
{
return true;
}
else
{
return false;
}
}
}
Debugging doesn't step into operator's body:
var b = (new Complex() == new Complex());

== operator overloading when object is boxed

The output of the below code is as following:
not equal
equal
Note the difference in type of x and xx and that == operator overload is only executed in the second case and not in the first.
Is there a way I can overload the == operator so that its always executed when a comparison is done on between MyDataObejct instances.
Edit 1:# here i want to override the == operator on MyDataClass , I am not sure how I can do it so that case1 also executes overloaded == implementation.
class Program {
static void Main(string[] args) {
// CASE 1
Object x = new MyDataClass();
Object y = new MyDataClass();
if ( x == y ) {
Console.WriteLine("equal");
} else {
Console.WriteLine("not equal");
}
// CASE 2
MyDataClass xx = new MyDataClass();
MyDataClass yy = new MyDataClass();
if (xx == yy) {
Console.WriteLine("equal");
} else {
Console.WriteLine("not equal");
}
}
}
public class MyDataClass {
private int x = 5;
public static bool operator ==(MyDataClass a, MyDataClass b) {
return a.x == b.x;
}
public static bool operator !=(MyDataClass a, MyDataClass b) {
return !(a == b);
}
}
No, basically. == uses static analysis, so will use the object ==. It sounds like you need to use object.Equals(x,y) instead (or x.Equals(y) if you know that neither is null), which uses polymorphism.
Here is a description on how to override Equals and the == operator:
http://msdn.microsoft.com/en-us/library/ms173147(VS.80).aspx
This is how it looks (provided that you have already made an overload of Equals()):
public static bool operator ==(MyDataClass a, MyDataClass 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;
}
// Otherwise use equals
return a.Equals(b);
}
public override bool Equals(System.Object obj)
{
// If parameter is null return false.
if (obj == null)
{
return false;
}
// If parameter cannot be cast to MyDataClass return false.
MyDataClass p = obj as MyDataClass;
if ((System.Object)p == null)
{
return false;
}
return (x == p.x);
}

Categories

Resources