Jak działa operator porównania z null int?

151

Zaczynam uczyć się typów dopuszczających wartość null i napotykam następujące zachowania.

Podczas próby zerowania int, widzę, że operator porównania daje nieoczekiwany wynik. Na przykład w moim kodzie poniżej otrzymane dane wyjściowe to „oba i 1 są równe” . Uwaga, nie wypisuje również „null”.

int? a = null;
int? b = 1;

if (a < b)
    Console.WriteLine("{0} is bigger than {1}", b, a);
else if (a > b)
    Console.WriteLine("{0} is bigger than {1}", a, b);
else
    Console.WriteLine("both {0} and {1} are equal", a, b);

Miałem nadzieję, że jakakolwiek nieujemna liczba całkowita będzie większa niż zero. Czy czegoś tu brakuje?

Ron5504
źródło
5
Oto małe skrzypce .NET, aby zobaczyć kilka przypadków.
Uwe Keim

Odpowiedzi:

207

Według MSDN - na dole strony w sekcji „Operatorzy”:

Podczas przeprowadzania porównań z typami dopuszczającymi wartość null, jeśli wartość jednego z typów dopuszczających wartość null jest, nulla drugiego nie, wszystkie porównania są obliczane na falsez wyjątkiem!=

Więc oba a > bi a < boceniaj, falseponieważ ajest null ...

nkvu
źródło
2
W swoich projektach używam obecnie VB.NET i wygląda na to, że nothing <> 1= nullw VB, podczas gdy null != 1= truew C # - używam LinqPada do testowania instrukcji
Luke T O'Brien
2
Właśnie się zastanawiałem i warto o tym wspomnieć Lifted Operatorsw C # stackoverflow.com/questions/3370110/what-are-lifted-operators - zastanawiałem się, czy to może być powód, dla którego VB.NET zwraca różne wyniki
Luke T O'Brien
44

Jak mówi MSDN

Podczas wykonywania porównań z typami dopuszczającymi wartość null, jeśli wartość jednego z typów dopuszczających wartość null jest równa null, a drugiego nie, wszystkie porównania są oceniane na false z wyjątkiem! = (Nie równe). Ważne jest, aby nie zakładać, że ponieważ dane porównanie zwraca fałsz, odwrotny przypadek zwraca prawdę. W poniższym przykładzie 10 nie jest większe niż, mniejsze niż ani równe null. Tylko num1! = Num2 daje w wyniku prawda.

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
 */
Parimal Raj
źródło
25

Podsumowując: wszelkie porównania nierówność z wartością null ( >=, <, <=, >) zwraca falsenawet jeśli oba argumenty są nieważne. to znaczy

null >  anyValue //false
null <= null     //false

Każde porównanie równości lub nierówności z null ( ==, !=) działa „zgodnie z oczekiwaniami”. to znaczy

null == null     //true
null != null     //false
null == nonNull  //false
null != nonNull  //true
GDS
źródło
Czy to samo dotyczy obu int? nonNulli int notNull?
Кое Кто
1
@ КоеКто, To samo zachowanie dotyczy Nullable<NumberTypes> = null. Zweryfikowano.
Artru
2

Porównanie C # z SQL

C #: a = null i b = null => a == b => true

SQL: a = null i b = null => a == b => false

Gunnar Siréus
źródło