Порядок операторов в выражении IF - PullRequest
3 голосов
/ 07 октября 2010

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

// Example #1
if (cats != null && cats.Count > 0)
{
  // Do something
}

В # 1 я всегда просто предполагал, что cats != null должен быть первым, потому что порядок операций оценивается слева направо.

Однако в отличие от пример # 1, теперь я хочу сделать что-то, если объект null или Countноль, поэтому я использую логическое ИЛИ вместо И:

// Example #2
if (table == null || table.Rows == null || table.Rows.Count <= 0)
{
  // Do something
}

Имеет ли значение порядок логических сравнений?Или я могу также изменить порядок и получить те же результаты, как в примере № 3?

// Example #3
if (table.Rows.Count <= 0 || table.Rows == null || table == null)
{
  // Do something
}

(кстати, я понимаю, что могу переписать № 2, как показано ниже, но ядумаю, что это грязно, и мне все еще интересно, операторы ИЛИ)

// Example #4
if (!(table != null && table.Rows != null && table.Rows.Count > 0))
{
  // Do something
}

Ответы [ 6 ]

11 голосов
/ 07 октября 2010

В приведенном вами примере:

if (table == null || table.Rows == null || table.Rows.Count <= 0)
{
  // Do something
}

... ни table.Rows, ни table.Rows.Count не будут разыменовываться, если tables равно нулю.

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

Рассмотрим этот код:

bool A()
{
    return false;
}

bool B()
{
    return true;
}

//...

if (A() && B())
{
    // do something
}

Чтобы предложение AND было истинным, все элементы должны быть истинными. Однако A() возвращает false, и среда выполнения (или, может быть, компилятор здесь, на этапе оптимизации, но давайте не будем об этом беспокоиться ...) вообще не будет оценивать B().

То же самое верно для выражений OR (||). Если какой-либо элемент в предложении равен true, вычисляется слева направо, остальная часть предложения не будет выполнена.

2 голосов
/ 07 октября 2010

Следует отметить, что не все логические операторы C # демонстрируют поведение с коротким замыканием (как было указано выше).

Вы используете оператор условного AND (&&), и это вызывает короткое замыкание.Однако оператор AND (&) точно такой же, как и оператор Conditional-AND без короткого замыкания.

То же самое верно для операторов OR и Conditional-OR.

Например:

// Это будет сгенерировать, если коты имеют нулевое значение, в любом порядке.

if (cats! = Null & cats.Count> 0) {}

// Это не будет.Из-за короткого замыкания.

if (cats! = Null && cats.Count> 0) {}

2 голосов
/ 07 октября 2010

Да, короткое замыкание происходит в обоих случаях, с той лишь разницей, что && останавливается, если LHS ложно (потому что тогда общее выражение должно быть ложным), пока || останавливается, если LHS истинно (потому что общее выражение должно быть истинным).

Первые два примера в вашем вопросе верны, третий вызовет исключение, если таблица или таблица. Строки равны нулю.

0 голосов
/ 07 октября 2010

Первая конструкция не такая, как вторая. Первый - использовать, если вы не хотите ничего делать, когда ссылка равна нулю или если Счетчик равен нулю. Вторая конструкция будет DO чем-то, когда она равна нулю или счетчик равен нулю ... Чтобы сделать вторую такую ​​же, как первая, вам нужно написать:

 if (table == null || table.Rows == null || table.Rows.Count <= 0 || ) 
 {}
 else
 { 
  // Do something 
 } 

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

0 голосов
/ 07 октября 2010

Порядок не имеет значения.

Уточнение:

Порядок, в котором вы размещаете операторы в операторе IF, не повлияет на выполнение оператора IF ... и, следовательно, нарезультат.

Как указал другой автор, это, однако, повлияет на то, какие из них оцениваются, но не влияет на нижнюю строку AFAIK.

Edit @ JonHanna

IПолагаю, я смотрел на это с точки зрения того, что ОП заявил, что он проверяет наличие ранее NPE, когда это необходимо (см. первую строку своего поста).Так что, если его код не выдает ошибок во время выполнения, то порядок ничего не значит.Я не могу себе представить, почему кто-то может кодировать оператор IF с мыслительным процессом «если этот оператор IF вызывает NPE», то он не будет оценен ...

0 голосов
/ 07 октября 2010

Заказ имеет значение. Все дело в коротком замыкании. Для ands, первое ложное срабатывание перестает оцениваться, для OR останавливается, как только встречается true.

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

Когда вы думаете об этом, подумайте, вставьте null для каждого объекта.

if (null== null || null.Rows == null || null.null.Count <= 0)
{
  // Do something
}

Затем оцените каждый логический

if( true || null.Rows == null || null.null.Count <=0)

Если вы видите истину, это означает остановку. Если вы нажмете «ноль». заявление, что вы потерпите крах.

Пример для иллюстрации сбоя

if (null.null.Count <= 0 || null.Rows == null || null== null)
{
  // CRASH... Do something
}
...