Оценка короткого замыкания - это гарантировано? [C #] - PullRequest
16 голосов
/ 22 апреля 2010

Быстрый вопрос здесь о коротких замыканиях в C #. С оператором if, подобным этому:

if (MyObject.MyArray.Count == 0 || MyObject.MyArray[0].SomeValue == 0)
{

//....
}

Гарантируется ли, что оценка прекратится после части «MyArray.Count», если эта часть истинна? В противном случае я получу нулевое исключение во второй части.

Ответы [ 6 ]

34 голосов
/ 22 апреля 2010

Да, это гарантировано.

C # Спецификация языка - 7.11 Условные логические операторы :

Вызваны операторы && и ||условные логические операторы. Их также называют "короткозамкнутыми" логическими операторами.

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

Теперь важно провести различие между условным оператором и логическим оператором:

  • Только условные операторы поддерживают короткое замыкание, логические операторы - нет.
  • Логические операторы C # выглядят так же, как их условные аналоги, но с одним символом меньше, поэтому логическое ИЛИ равно |, а логическое И - &.
  • Логические операторы могут быть перегружены, но условные операторы не могут (это немного технически, поскольку оценка условного оператора действительно включает разрешение перегрузки, и это разрешение перегрузки может преобразовываться в настраиваемую перегрузку логического оператора типа, поэтомуВы можете обойти это ограничение в определенной степени).
12 голосов
/ 22 апреля 2010

Да, это гарантировано.

http://msdn.microsoft.com/en-us/library/6373h346%28v=VS.80%29.aspx

Оператор условного ИЛИ (||) выполняет логическое ИЛИ своих операндов bool, но вычисляет свой второй операнд только при необходимости.

5 голосов
/ 22 апреля 2010

Да, это гарантировано, но вы все равно можете получить исключение нулевой ссылки, если MyArray равен нулю (или MyObject в этом отношении очевидно).

2 голосов
/ 01 мая 2016

Да,

Для операций И, если какой-либо из операндов оценивается как ложный, тогда общее выражение оценивается как ложный, тогда нет необходимости оценивать оставшиеся выражения, И в случае операции ИЛИ, если любой изоперанд оценивается как true, тогда оставшаяся оценка может быть пропущена

Таким образом, используя && или ||Оператор, все выражение может быть оценено как true или false без оценки всех подвыражений.

Но учтите также побочный эффект . Эта статья может быть полезна для глубокого понимания оценки короткого замыкания на примерах из реального мира.

2 голосов
/ 22 апреля 2010

Просто небольшое наблюдение.

Вы сказали это:

В противном случае я получу нулевое исключение во второй части.(подчеркивает мою)

На самом деле это не так.Если короткое замыкание не гарантировано, вы можете получить IndexOutOfRangeException во второй части.

Это все еще возможно, вы можете получить NullReferenceException, если первый элемент в вашемMyArray объект фактически равен нулю (или если любой из других объектов в этом выражении равен).

Единственная полностью безопасная проверка будет такой:*

bool conditionHolds =
    MyObject == null ||
    MyObject.MyArray == null ||
    MyObject.MyArray.Count == 0 ||
    MyObject.MyArray[0] == null ||
    MyObject.MyArray[0].SomeValue == 0;

if (conditionHolds)
{
    //....
}
0 голосов
/ 22 апреля 2010

Я предпочитаю использовать оператор &&, потому что тогда вы тестируете положительное значение (мой массив содержит элементы), а не отрицательное (моя ошибка не содержит элементы):

if (MyObject.MyArray.Count > 0 && MyObject.MyArray[0].SomeValue == 0) 
{ 

//.... 
} 

Это также гарантированнокороткое замыкание.

...