C# хорошо со сравнением значения вводит к пустому указателю

Я столкнулся с этим сегодня, и понятия не имейте, почему компилятор C# не бросает ошибку.

Int32 x = 1;
if (x == null)
{
    Console.WriteLine("What the?");
}

Я смущен относительно того, как x мог когда-либо возможно быть пустым. Тем более, что это присвоение определенно бросает ошибку компилятора:

Int32 x = null;

Действительно ли возможно, что x мог стать пустым, Microsoft просто решила не поместить, это зарегистрировалось в компиляторе, или это было пропущено полностью?

Обновление: После питания с кодом для написания этой статьи внезапно компилятор придумал предупреждение, что выражение никогда не будет верно. Теперь я действительно потерян. Я поместил объект в класс, и теперь предупреждение ушло, но уехало с вопросом, может тип значения заканчивать тем, что был пустым.

public class Test
{
    public DateTime ADate = DateTime.Now;

    public Test ()
    {
        Test test = new Test();
        if (test.ADate == null)
        {
            Console.WriteLine("What the?");
        }
    }
}
85
задан Joshua Belden 7 October 2011 в 15:39
поделиться

7 ответов

Это законно, потому что разрешение перегрузки оператора имеет уникальный лучший выбор. Есть оператор ==, который принимает два nullable ints. Локальная int преобразуется в nullable int. Нулевой литерал преобразуется в nullable int. Следовательно, это легальное использование оператора ==, и всегда будет приводить к false.

Аналогично, мы также позволяем сказать "if (x == 12.6)", что также всегда будет ложным. int local конвертируется в double, литерал конвертируется в double, и очевидно, что они никогда не будут равны.

.
118
ответ дан 24 November 2019 в 08:20
поделиться

Тип значения не может быть нулем , хотя может быть равен нулю (обратите внимание на Nullable<>). В вашем случае переменная int и null неявно присваиваются к Nullable и сравниваются.

.
1
ответ дан 24 November 2019 в 08:20
поделиться

Нет, Int32 x никогда не станет нулем .

Если вы сравниваете int с нулем. затем оператор сравнения, который применим два int?s.

"Почему сравнение типа значения с нулем является предупреждением?" статья поможет вам.

3
ответ дан 24 November 2019 в 08:20
поделиться

Это не ошибка, так как происходит (int?) приведение, а предупреждение в приведенном примере:

Результатом выражения всегда является 'false', так как значение типа 'int' никогда не бывает равно 'null' типа 'int? '

Если вы проверите IL, то увидите, что она полностью удаляет недоступную ветку - ее нет в сборке релиза.

Однако, следует заметить, что она не выдает это предупреждение для пользовательских структур с операторами равенства. Так было в 2.0, но не в компиляторе 3.0. Код все равно удален (чтобы знать, что код недоступен), но предупреждение не выдается:

using System;

struct MyValue
{
    private readonly int value;
    public MyValue(int value) { this.value = value; }
    public static bool operator ==(MyValue x, MyValue y) {
        return x.value == y.value;
    }
    public static bool operator !=(MyValue x, MyValue y) {
        return x.value != y.value;
    }
}
class Program
{
    static void Main()
    {
        int i = 1;
        MyValue v = new MyValue(1);
        if (i == null) { Console.WriteLine("a"); } // warning
        if (v == null) { Console.WriteLine("a"); } // no warning
    }
}

С IL (для Main) - обратите внимание все , кроме MyValue(1) (который мог иметь побочные эффекты), было удалено:

.method private hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 2
    .locals init (
        [0] int32 i,
        [1] valuetype MyValue v)
    L_0000: ldc.i4.1 
    L_0001: stloc.0 
    L_0002: ldloca.s v
    L_0004: ldc.i4.1 
    L_0005: call instance void MyValue::.ctor(int32)
    L_000a: ret 
}

это в основном:

private static void Main()
{
    MyValue v = new MyValue(1);
}
17
ответ дан 24 November 2019 в 08:20
поделиться

Я подозреваю, что компилятор просто оптимизирует ваш конкретный тест при генерации IL, так как тест никогда не будет ложным.

Боковая заметка: Возможно вместо этого использовать Int32? x.

.
0
ответ дан 24 November 2019 в 08:20
поделиться

Тот факт, что сравнение никогда не может быть правдой, не означает, что оно незаконно. Тем не менее, нет, тип значения никогда не может быть null.

.
5
ответ дан 24 November 2019 в 08:20
поделиться

Полагаю, это потому, что "==" - это синтаксический сахар, который на самом деле представляет собой вызов метода System.Object.Equals, который принимает параметр System.Object. Null по спецификации ECMA является специальным типом, который, конечно, является производным от System.Object.

Поэтому есть только предупреждение.

.
0
ответ дан 24 November 2019 в 08:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: