Reputation: 90465
When I have to implement equality comparers for
public class SampleClass
{
public int Prop { get; set; }
}
Should I make
null == new SampleClass()
and
new SampleClass() == null
and
new SampleClass().Equals(null)
false?
And what about
new SampleClass() != null
Should it be also false?
UPDATE People are questioning the reasoning behind this question. It's supposed that != and == be always opposites. But if I implement the methods so all those comparisons above results in false, there will be a case where the == and != operators will result the same result. So it's a dilemma whether != should return true or false.
Upvotes: 3
Views: 417
Reputation: 113232
I think this is a particularly interesting question. I've a take on it that isn't exactly the same as any of the answers, so bear with my coming to it so late.
The first thing to note, is that null
in .NET is not entirely the same as null
in some other contexts, though it can be used to model them.
In SQL for example, we might have 1 = null
and 1 <> null
both return null
, because it's concept of null
is closer to the mathematical, in which null is not equal to anything, including null, but nor is it precisely unequal to anything.
We can use C# null
for this if we want, but that's not quite how the default meaning of null
in .NET works.
For any reference type, null has a specific defined meaning, and possibly additional meanings provided by context.
The specific meaning is "there is no instance of this an object of this type".
Additional meanings in a given context could be "the integer value is in fact null, rather than matching any integer", or "there is no such collection of items, not even an empty one", or "this is the first such item, so there is no earlier one" and so on depending on how we make use of it. (Also, it could mean "oh dear, that really wasn't supposed to be null, better throw an exception").
Now, we might want to make heavy use of those additional meanings, to such an extent that we define cases in which it is meaningful for an object to be equal to null, or at the very least not unequal to null. However, we have the following limitations:
The specific definition that null for a value of a reference type means there is no instance of that reference type will not go away.
The semantics that x == y
will always give the opposite result to x != y
for a given x and y, will not go away.
Therefore:
If we want a type where an instance can be equal to null, it must be a value type.
We still have to have x != null
return the opposite to x == null
.
Now, since .NET 2.0 we've had a built-in that does precisely that: Nullable<T>
(or T?
in C# syntax). It also has a bit of extra support to help it behave well in the face of boxing (which makes it in man ways behave like a reference type, so without that extra support we'd have complications were x == null
would return true but (object)x == null
would return false.
It's also the case, that Nullable<T>
can deal with pretty much any case in which we'd like to make use of this sort of slightly different semantics for null, meaning there isn't really any case left were we're likely to want to define an Equals()
method that returns true when passed null.
Upvotes: 0
Reputation: 25339
As well as what has been stated, note that:
The predefined reference type equality operators are:
bool operator ==(object x, object y);
bool operator !=(object x, object y);
So....
SampleClass a = null;
SampleClass b = null;
Read what the .NET framework designers said on the question:
Why don't nullable relational operators return “bool?” instead of “bool“?
For more info, read:
Upvotes: 2
Reputation: 48476
All the equality comparions with null from your example should definitely be false. The last one is also very important however:
new SampleClass() != null
This must definitely evaluate to true
, because this is a common way to check if a reference variable has been initialized. If it were to evaluate to false
, it might unintentionally reassign the variable all over the place, because C# developers expect a certain kind of behavior from there operators. Another example:
SampleClass myVar = new SampleClass();
// Various stuff happening here, possibly setting myVar to null
if (myVar != null)
{
// Programmer go "WTFBBQ?" when he finds this doesn't get executed
myVar.DoStuff();
}
Confused, the programmer changes this to:
if (myVar == null)
{
myVar = new SampleClass();
}
myVar.DoStuff(); // null reference exception, huh?
Upvotes: 4
Reputation: 191865
Is it even a question? No, null
should never be equal to an object.
Edit: And thus by extension, new SampleClass() != null
should be true
. null
isn't like NaN
; it's pretty well-defined.
Upvotes: 7
Reputation: 6157
Null should never compare as equal to a non-null reference. By extension, your != should return true as it is the opposite of the equality.
Upvotes: 1
Reputation: 15785
If you have an instance of an object, you do not have null and all equality comparers should respect this.
Upvotes: 0
Reputation: 10782
As others have said, null can never be equal to anything else including null. This is because null isn't a value, rather it is a lack of a value.
For your specific question, it seems like you are trying to instantiate an object that has not yet been initialized and you want to determine whether or not that object has been initialized. My suggestion would be to include a property that indicates whether or not the object has been initialized.
Upvotes: 1
Reputation: 34632
I'm not sure I fully understand your question, but null is (by definition) not a value. As such,
null == new SampleClass()
doesn't really make any sense (and, really, none of the other comparisons do).
Can you rephrase your question?
Upvotes: 1