C # логический порядок и поведение компилятора - PullRequest
16 голосов
/ 08 августа 2008

В C # (и не стесняйтесь отвечать за другие языки), в каком порядке среда выполнения оценивает логическое утверждение?

Пример:

DataTable myDt = new DataTable();
if (myDt != null && myDt.Rows.Count > 0)
{
    //do some stuff with myDt
}

Какой оператор среда выполнения оценивает первым -

myDt != null

или

myDt.Rows.Count > 0

Есть ли время, когда компилятор когда-либо оценивал бы утверждение в обратном направлении? Возможно, когда задействован оператор «ИЛИ»?


& известен как логический побитовый оператор и всегда вычисляет все подвыражения

Что является хорошим примером того, когда использовать побитовый оператор вместо "короткого замыкания"?

Ответы [ 18 ]

16 голосов
/ 08 августа 2008

C #: слева направо, и обработка останавливается, если найдено несоответствие (оценивается как ложное).

9 голосов
/ 08 августа 2008

"C #: слева направо, и обработка останавливается, если найдено совпадение (оценивается как true)."

Овца-зомби не права, недостаточно представителей, чтобы проголосовать за нее.

Вопрос касается оператора &&, а не оператора || оператор.

В случае && оценка остановится, если будет найдено ЛОЖЬ.

В случае || оценка останавливается, если ИСТИНА найдена.

8 голосов
/ 08 августа 2008

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

В таких языках, как C ++, где вы можете перегружать поведение && и || операторы, настоятельно рекомендуется, чтобы вы не делали этого . Это потому, что когда вы перегружаете это поведение, вы в конечном итоге форсируете оценку обеих сторон операции. Это делает две вещи:

  1. Это нарушает механизм отложенного вычисления, потому что перегрузка - это функция, которая должна вызываться, и, следовательно, оба параметра оцениваются перед вызовом функции.
  2. Порядок оценки указанных параметров не гарантируется и может зависеть от компилятора. Следовательно, объекты не будут вести себя так же, как в примерах, перечисленных в вопросе / предыдущих ответах.

Для получения дополнительной информации прочитайте книгу Скотта Мейерса, Более эффективный C ++ . Ура!

6 голосов
/ 08 августа 2008

vb.net

if( x isNot Nothing AndAlso x.go()) then
  1. Оценка проводится слева направо
  2. AndAlso оператор гарантирует, что только если левая сторона была ИСТИНА, правая сторона будет оценена (очень важно, так как, если x - ничто, x.go потерпит крах)

Вы можете использовать И вместо And Также в vb. в этом случае левая сторона также оценивается первой, но правая будет оцениваться независимо от результата.

Лучшая практика: всегда используйте AndAlso, если только у вас нет веских причин, почему бы и нет.


В последующем спросили, почему или когда кто-то будет использовать И вместо AndAlso (или & вместо &&): Вот пример:

if ( x.init() And y.init()) then
   x.process(y)
end 
y.doDance()

В этом случае я хочу инициализировать оба X и Y. Y должен быть инициализирован, чтобы y.DoDance мог выполняться. Тем не менее, в функции init () я также делаю некоторые дополнительные вещи, такие как проверка, открыт ли сокет, и только если это работает нормально, для и , я должен пойти дальше и выполнить x.process ( у).

Опять же, это, вероятно, не нужно и не элегантно в 99% случаев, поэтому я сказал, что по умолчанию должно использоваться AndAlso .

5 голосов
/ 08 августа 2008

@ shsteimer

Понятие «скромность» относится к перегрузке оператора. в заявлении: ... A оценивается первым, если оно оценивается как ложное, B никогда не оценивается. То же относится и к

Это не перегрузка оператора. Перегрузка операторов - это термин, который позволяет определять пользовательское поведение для операторов, например *, +, = и т.

Это позволит вам написать свой собственный класс 'Log', а затем сделать

a = new Log(); // Log class overloads the + operator
a + "some string"; // Call the overloaded method - otherwise this wouldn't work because you can't normally add strings to objects.

Делаем это

a() || b() // be never runs if a is true

фактически называется Оценка короткого замыкания

4 голосов
/ 08 августа 2008

В некоторых языках возникают интересные ситуации, когда выражения выполняются в другом порядке. Я специально думаю о Ruby, но я уверен, что они позаимствовали его из других источников (вероятно, Perl).

Выражения в логике останутся слева направо, но, например:

puts message unless message.nil?

Выше будет оцениваться "message.nil?" во-первых, затем, если оно оценивается как ложное (если не похоже на if, если только оно выполняется, когда условие ложно, а не истина), выполняется «кладет сообщение», которое выводит содержимое переменной сообщения на экран.

Иногда это интересный способ структурировать ваш код ... Лично мне нравится использовать его для очень коротких 1 строк, как указано выше.

Edit:

Чтобы сделать это немного понятнее, приведенное выше совпадает с:

unless message.nil?
  puts message
end
4 голосов
/ 08 августа 2008

Обратите внимание, что между && и & есть разница в отношении того, какая часть вашего выражения оценивается.

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

& известен как логический побитовый оператор и всегда вычисляет все подвыражения.

Как таковой:

if (a() && b())

Будет вызывать b , только если a вернет true .

однако, это:

if (a() & b())

всегда будет вызывать a и b , даже если результат вызова a ложен и, следовательно, известен как false независимо от результата вызова b .

Такая же разница существует для || и | операторы.

4 голосов
/ 08 августа 2008

ZombieSheep мертв. Единственная «ошибка», которая может ждать, это то, что это верно только в том случае, если вы используете оператор &&. При использовании оператора & оба выражения будут оцениваться каждый раз, независимо от того, будет ли одно или оба иметь значение false.

if (amHungry & whiteCastleIsNearby)
{
   // The code will check if White Castle is nearby
   // even when I am not hungry
}

if (amHungry && whiteCastleIsNearby)
{
   // The code will only check if White Castle is nearby
   // when I am hungry
}
2 голосов
/ 08 августа 2008

Понятие «скромность» относится к перегрузке оператора. в заявлении:

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

A оценивается первым, если оно оценивается как false, B никогда не оценивается. То же относится и к

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

A оценивается первым, если оно оценивается как true, B никогда не оценивается.

Эта концепция, перегруженная, применима (я думаю) ко всем языкам стиля Си, а также ко многим другим.

2 голосов
/ 08 августа 2008

Левый, затем останавливается, если он нулевой.

Редактировать: В vb.net он оценит оба и, возможно, выдаст ошибку, если вы не используете AndAlso

...