Почему в С# часто появляется "null!= Variable" вместо "variable!= Null"?

В С# есть ли разница в скорости исключения для порядка, в котором вы указываете условие?

if (null != variable) ...
if (variable != null) ...

С недавнего времени я видел первый довольно часто, и это привлекло мое внимание, так как я привык ко второму.

Если нет разницы, в чем преимущество первого?

Ответ 1

Это удержание от C. В C, если вы либо используете плохой компилятор, либо не имеете достаточно высоких предупреждений, это будет скомпилировано без каких-либо предупреждений (и это действительно легальный код):

// Probably wrong
if (x = 5)

когда вы на самом деле имели в виду

if (x == 5)

Вы можете обойти это в C, выполнив:

if (5 == x)

Опечатка здесь приведет к недействительному коду.

Теперь, в С#, это все piffle. Если вы не сравниваете два булевых значения (что редко, IME), вы можете написать более читаемый код, так как оператор "if" требует начала булевого выражения, а тип "x=5" - Int32, а не Boolean.

Я предлагаю, чтобы, если вы видите это в коде ваших коллег, вы воспитываете их в соответствии с современными языками и предлагаете писать более естественную форму в будущем.

Ответ 2

Есть веская причина сначала использовать null: if(null == myDuck)

Если ваш class Duck переопределяет оператор ==, тогда if(myDuck == null) может перейти в бесконечный цикл.

Использование null сначала использует компаратор сравнения по умолчанию и фактически делает то, что вы намеревались.

(Я слышал, вы привыкли читать код, написанный таким образом в конце концов - я еще не испытал это преобразование).

Вот пример:

public class myDuck
{
    public int quacks;
    static override bool operator ==(myDuck a, myDuck b)
    {
        // these will overflow the stack - because the a==null reenters this function from the top again
        if (a == null && b == null)
            return true;
        if (a == null || b == null)
            return false;

        // these wont loop
        if (null == a && null == b)
            return true;
        if (null == a || null == b)
            return false;
        return a.quacks == b.quacks; // this goes to the integer comparison
    }
}

Ответ 3

Я предполагаю, что это программист на языке С, который переключил языки.

В C вы можете написать следующее:

int i = 0;
if (i = 1)
{
    ...
}

Обратите внимание на использование одного знака равенства, означающего, что код присваивает 1 переменной i, затем возвращает 1 (присваивание является выражением) и использует 1 в if-statement, который будет обрабатываться как правда. Другими словами, вышесказанное является ошибкой.

Однако в С# это невозможно. Между ними нет никакой разницы.

Ответ 4

Как все уже отмечали, он приходит более или менее с языка C, где вы можете получить неверный код, если вы случайно забудете второй знак равенства. Но есть еще одна причина, которая также соответствует С#: читаемость.

Просто возьмите этот простой пример:

if(someVariableThatShouldBeChecked != null
   && anotherOne != null
   && justAnotherCheckThatIsNeededForTestingNullity != null
   && allTheseChecksAreReallyBoring != null
   && thereSeemsToBeADesignFlawIfSoManyChecksAreNeeded != null)
{
    // ToDo: Everything is checked, do something...
}

Если бы вы просто поменяли все нулевые слова на начало, вы можете намного проще определить все проверки:

if(null != someVariableThatShouldBeChecked
   && null != anotherOne
   && null != justAnotherCheckThatIsNeededForTestingNullity
   && null != allTheseChecksAreReallyBoring
   && null != thereSeemsToBeADesignFlawIfSoManyChecksAreNeeded)
{
    // ToDo: Everything is checked, do something...
}

Таким образом, этот пример может быть неудачным примером (см. рекомендации по кодированию), но просто подумайте о том, чтобы вы быстро прокрутили полный файл кода. Просто увидев шаблон

if(null ...

вы сразу узнаете, что будет дальше.

Если бы все было наоборот, вам всегда нужно сканировать до конца строки, чтобы увидеть проверку недействительности, просто давая вам на секунду наткнуться, чтобы узнать, какая проверка выполняется там. Поэтому возможно подсветка синтаксиса может помочь вам, но вы всегда медленнее, когда эти ключевые слова находятся в конце строки, а не спереди.

Ответ 5

В прежние времена люди забыли "!" (или дополнительный "=" для равенства, который сложнее определить) и вместо задания сопоставлять задание. поместив нуль впереди, исключает возможность ошибки, так как null не является l-значением (I.E. он не может быть назначен).

Большинство современных компиляторов дают предупреждение, когда вы выполняете задание в условном состоянии в настоящее время, а С# на самом деле дает ошибку. Большинство людей просто придерживаются схемы var == null, так как ее легче читать для некоторых людей.

Ответ 6

Я не вижу никакого преимущества в соблюдении этого соглашения. В C, где булевы типы не существуют, полезно написать

if( 5 == variable)

а не

if (variable == 5)

потому что, если вы забудете один из значков eaqual, вы получите

if (variable = 5)

который присваивает переменную 5 и всегда оценивает значение true. Но в Java логическое значение является булевым. И с! =, Нет никакой причины.

Один хороший совет, однако, состоит в том, чтобы написать

if (CONSTANT.equals(myString))

а не

if (myString.equals(CONSTANT))

потому что это помогает избежать NullPointerExceptions.

Моим советом было бы попросить оправдание правила. Если их нет, зачем им следовать? Это не помогает читабельности

Ответ 7

Для меня всегда был стиль, который вы предпочитаете

@Shy. Затем снова, если вы запутаете операторы, вы должны захотеть получить ошибку компиляции или у вас будет код с ошибкой - ошибка, которая вернется и укусит вас позже по дороге, так как она вызвала непредвиденное поведение

Ответ 8

Еще одна вещь... Если вы сравниваете переменную с константой (integer или string для ex.), то ставим константу слева - это хорошая практика, потому что вы никогда не столкнетесь с NullPointerExceptions:

int i;
if(i==1){        // Exception raised: i is not initialized. (C/C++)
  doThis();
}

тогда

int i;
if(1==i){        // OK, but the condition is not met.
  doThis();
}

Теперь, поскольку по умолчанию С# инициализирует все переменные, вы не должны иметь эту проблему на этом языке.