Математические операции с нулевым
Пожалуйста, объясните, почему проходит этот тест?
[Test]
public void TestNullOps()
{
Assert.That(10 / null, Is.Null);
Assert.That(10 * null, Is.Null);
Assert.That(10 + null, Is.Null);
Assert.That(10 - null, Is.Null);
Assert.That(10 % null, Is.Null);
Assert.That(null / 10, Is.Null);
Assert.That(null * 10, Is.Null);
Assert.That(null + 10, Is.Null);
Assert.That(null - 10, Is.Null);
Assert.That(null % 10, Is.Null);
int zero = 0;
Assert.That(null / zero, Is.Null);
}
Я не понимаю, как этот код даже компилируется.
Похоже, каждое математическое выражение с нулевым возвратом Nullable<T>
(например, 10 / null
является Nullable<int>
). Но я не вижу операторных методов в классе Nullable<T>
. Если эти операторы взяты из int
, почему последнее утверждение не терпит неудачу?
Ответы
Ответ 1
От MSDN:
Предопределенные унарные и двоичные операторы и любые пользовательские операторы, которые существуют для типов значений, также могут использоваться типами с нулевым значением. Эти операторы производят нулевое значение, если операнды равны нулю; в противном случае оператор использует содержащееся значение для вычисления результата.
Итак, почему все тесты пройдены, включая последний, независимо от значения операнда, если другой операнд null
, тогда результат будет null
.
Ответ 2
Операторы для Nullable<T>
являются так называемыми "поднятыми" операторами]; компилятор С# принимает операторы, доступные для T
, и применяет набор предопределенных правил; например, с +
, поднятый +
равен null
, если один из операндов равен null, иначе сумма внутренних значений. Повторить последнее; снова, деление определяется как null
, если либо операнд null
- он никогда не выполняет деление.
Ответ 3
Я бы предположил, что компилятор преобразует zero
в Nullable<int>
и предоставляет базовый оператор разделения. Так как тип Nullable
может быть нулевым, деление на 0 не происходит во время компиляции. Лучше всего предположить, что они хотят, чтобы вы могли выполнять нулевое тестирование в случаях, когда происходит div/0.
Ответ 4
Я попытался увидеть сгенерированный код из приведенного ниже кода с помощью рефлектора
var myValue = 10 / null;
И компилятор превращает его в это:
int? myValue = null;
И это не скомпилируется, поэтому вы не можете его обмануть:
object myNull = null;
var myValue = 10 / myNull;
Ответ 5
Операции в этом списке всегда возвращают NULL:
1 + 2 + 3 + NULL
5 * NULL - 7
'Home ' || 'sweet ' || NULL
MyField = NULL
MyField <> NULL
NULL = NULL