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 ch开发者_开发技巧eck.
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());
精彩评论