ChatGPT解决这个技术问题 Extra ChatGPT

Why does >= return false when == returns true for null values?

I have two variables of type int? (or Nullable if you will). I wanted to do a greater-than-or-equal (>=) comparison on the two variables but as it turns out, this returns false if both variables are null, while obviously the == operator returns true.

Can someone explain to me why that is logical because the semantical definition of the >= operator contains the word "or"?

Can you post the code that produces this weird behavior?
Actually, I would question whether it is appropriate for == to return true. I don't think that is appropriate at all. How can two variables whose value is unknown be certified as equal ?
@Charles, because, if they are of the same nulled type (e.g. int?), then their value is known. null.
@moo-juice, Not in my world... If your name is null, would you answer to that? null is not the same as "null". There's an old movie called "My name is Nobody" ("Who broke the glass, children? " ---- "Nobody" ) So who is "Nobody"? In the real world, (outside of the code internals), null means the value is unknown.... The data structure value may be known (it is Null) but the real problem domain entity/value that the variable is there to represent is Not known..
@Charles, love the analogy!. But who didn't break the glass?

C
Christian Gollhardt

There was a huge debate about this oddity when the feature was originally designed back in C# 2.0. The problem is that C# users are completely used to this being meaningful:

if(someReference == null)

When extending equality to nullable value types, you have the following choices.

Nullable equality is truly lifted. If one or both of the operands is null then the result is neither true, nor false, but null. In this case you can either: a) Make it illegal to have a nullable value type equality in an if statement, because the if statement needs a bool, not a nullable bool. Instead, require everyone to use HasValue if they want to compare to null. This is verbose and irritating. b) Automatically convert null to false. The downside of this is that x==null returns false if x is null, which is confusing and works against people's understanding of null comparisons with reference types. Nullable equality is not lifted. Nullable equality is either true or false, and comparison to null is a null check. This makes nullable equality inconsistent with nullable inequality.

None of these choices is obviously correct; they all have pros and cons. VBScript chooses 1b, for example. After much debate the C# design team chose #2.


How is nullable equality inconsistent with nullable inequality in choice #2?
@MCS: In exactly the way that motivates the question in the first place. == can be true when <= is false.
@Eric: Thanks - I thought 'inequality' referred only to != which actually is consistent with ==. Didn't realize it's a mathematical term: en.wikipedia.org/wiki/Inequality_(mathematics).
Well, the other issue (which you haven't addressed) is what to do when you try to do <, <=, =>, or > when one of the operands is null. In C#, the answer is return false. In the Scala/Java String class, the answer is to throw a NullPointerException.
@Brian: then why allow the operators on nullable types at all? If they always throw on the null value of the nullable type then you might as well just define the operator only on the non-nullable types and make the user insert the conversion to non-nullable, since that's what they're going to have to do to eliminate the exception.
H
Henk Holterman

Because Equality is defined separately from Comparability.
You can test x == null but x > null is meaningless. In C# it will always be false.


+1: here's the MSDN link msdn.microsoft.com/en-us/library/2cf62fcy.aspx, but unfortunately, they forgot to explain the comparison operators behavior in case of 2 nulls (they mentioned only equality)...
yes, but the operator is greater than or equal. I see the truth table, but I would tend to agree with the OP, >= is greater or equal, if null==null is true, null>=null should also be true. I guess we just chalk it up to implementation and user convenience to preserve the ==null checks.
@David, see Eric's answer, "None of these choices is obviously correct". But in general, when a type is Equatable but not Comparable then >= is simply not defined.
D
Dan J

Another way of describing '>=' is: Not Less Than. No mention of equals. As soon as one of the operands in a non-equality test is Null, the result is unknown as well (is null). However if you want to know if both operands are Null, then Null == Null is a reasonable test (should result in true). Getting rid of the inequality part of the operator makes all the difference.

The following code example from http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx#sectionToggle4 summarizes how C# treats Null:

int? num1 = 10;   
int? num2 = null;   
if (num1 >= num2)   
{   
    Console.WriteLine("num1 is greater than or equal to num2");   
}   
else   
{   
    // This clause is selected, but num1 is not less than num2.   
    Console.WriteLine("num1 >= num2 returned false (but num1 < num2 also is false)");   
}   

if (num1 < num2)   
{   
    Console.WriteLine("num1 is less than num2");   
}   
else   
{   
    // The else clause is selected again, but num1 is not greater than   
    // or equal to num2.   
    Console.WriteLine("num1 < num2 returned false (but num1 >= num2 also is false)");   
}   

if (num1 != num2)   
{   
    // This comparison is true, num1 and num2 are not equal.   
    Console.WriteLine("Finally, num1 != num2 returns true!");   
}   

// Change the value of num1, so that both num1 and num2 are null.   
num1 = null;   
if (num1 == num2)   
{   
    // The equality comparison returns true when both operands are null.   
    Console.WriteLine("num1 == num2 returns true when the value of each is null");   
}   

/* Output:   
 * num1 >= num2 returned false (but num1 < num2 also is false)   
 * num1 < num2 returned false (but num1 >= num2 also is false)   
 * Finally, num1 != num2 returns true!   
 * num1 == num2 returns true when the value of each is null   
 */   

That's an interesting mental model. However Section §1.4 of the C# Spec call these operators Less Than Or Equal and Greater than or equal
@Conrad Which just illustrates the problems of translating a programming language (C# in this case) into english. IMHO, whenever Nulls figure into logic, you need to deal with a tri-state result (true, false, unknown). Any expression involving Null should result in unknown with the one exception of Null == x which is an explicit test for unknown resulting in either true or false.
@NealB: Actually, the spec states that >= and <= mean what you'd expect them to mean- section §7.10 makes it clear that the operation 'x op y' for <= and >= is meant to be equal-to or greater-than/less-than, as one would expect.
A
Aaron McIver

>= operates on a numeric value; which null is not.

You could overload the >= operator to provide what you desire on a specific type.


it does operate on null types, it returns false
It handles null types yes...semantics on what we are going to define as "operates". Defensive coding; is it null then do x versus treating null as a literal value when making decisions during the evaluation.
You cannot usually overload operators because you can only define them inside their own classes. So in this case you would need access to Nullable<T>'s code.
S
Sam

NULL is not zero (numeric or binary value), a zero-length string, or blank (character value). So any comparison operator will always return false on it. Read more about it here


Database NULL is not C# null. Furthermore, comparison operators on C# nullable types are a strange beast that do not necessarily follow the usual rules for null comparisons.
The answer is still right, just the link is wrong. msdn.microsoft.com/en-us/library/2cf62fcy.aspx#sectionToggle4
@unholy: The answer is wrong, and more importantly, it's based on wrong reasoning.
B
Bengie

What values would you expect?

null == null true

null >= null false

null > null false

null <= null false

null < null false

null != null false

1 == null false

1 >= null false

1 > null false

1 <= null false

1 < null false

1 != null true aka !(1 == null)


S
Sparr

>= only means "greater than or equal" when used in that specific well defined way. When used on a class with overloaded operators it means anything the class developer wants it to mean. When applied to a string-like class, it might mean "sorts the same or higher" or it might mean "the same length or longer".


M
Mayer Spitz

Since by default an int cannot be null and its value will be set to 0, the operator of > and < which is built for int type, expects to work with values and not with nulls.

see my answer to a similar question where I wrote some ways to handle nullable int with the less < and greater > operators https://stackoverflow.com/a/51507612/7003760