В C# (и не стесняйтесь отвечать для других языков), в каком порядке среда выполнения оценивает логический оператор?
Пример:
DataTable myDt = new DataTable();
if (myDt != null && myDt.Rows.Count > 0)
{
//do some stuff with myDt
}
Какой оператор сначала оценивает среда выполнения -
myDt != null
или же:
myDt.Rows.Count > 0
?
Было ли время, когда компилятор когда-либо оценивал оператор в обратном порядке? Возможно, когда задействован оператор «ИЛИ»?
& is known as a logical bitwise operator and will always evaluate all the sub-expressions
Каков хороший пример использования побитового оператора вместо «короткозамкнутого логического»?





Левый, затем останавливается, если он равен нулю.
Обновлено: в vb.net он оценит оба и, возможно, выдаст ошибку, если вы не используете AndAlso
C#: слева направо, и обработка останавливается, если обнаружено несоответствие (оценивается как ложное).
Я где-то слышал, что компиляторы работают в обратном порядке, но я не уверен, насколько это верно.
vb.net
if ( x isNot Nothing AndAlso x.go()) then
Вы можете использовать И вместо AndAlso в vb. в этом случае левая сторона также оценивается первой, но правая сторона оценивается независимо от результата.
Лучшая практика: всегда используйте AndAlso, если у вас нет веской причины, почему бы не делать этого.
В последующем спросили, почему и когда кто-то будет использовать And вместо AndAlso (или & вместо &&): Вот пример:
if ( x.init() And y.init()) then
x.process(y)
end
y.doDance()
В этом случае я хочу инициировать как X, так и Y. Y должен быть инициализирован, чтобы y.DoDance мог выполняться. Однако в функции init () я делаю еще кое-что, например, проверяю, что сокет открыт, и только если это сработает, для обе я должен продолжить и выполнить x.process (y).
Опять же, это, вероятно, не нужно и не элегантно в 99% случаев, поэтому я сказал, что по умолчанию следует использовать А также.
Под скромностью подразумевается перегрузка оператора. в заявлении:
if ( A && B){
// do something
}
Сначала оценивается A, если он оценивается как ложь, B никогда не оценивается. То же самое относится и к
if (A || B){
//do something
}
Сначала оценивается A, если оно истинно, B никогда не оценивается.
Эта концепция перегрузки применима (я думаю) ко всем языкам стиля C, а также ко многим другим.
ZombieSheep беспощаден. Единственный "подводный камень", который может подождать, - это то, что это верно только в том случае, если вы используете оператор &&. При использовании оператора & оба выражения будут оцениваться каждый раз, независимо от того, оценивается ли одно или оба как ложные.
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
}
Обратите внимание, что существует разница между && и & относительно того, какая часть вашего выражения оценивается.
&& известен как логическое логическое И с коротким замыканием, и, как отметили другие здесь, остановится раньше, если результат может быть определен до того, как будут оценены все подвыражения.
& известен как логический побитовый оператор и всегда вычисляет все подвыражения.
В качестве таких:
if (a() && b())
Будет вызывать б, только если а возвращает истинный.
однако это:
if (a() & b())
Всегда будет вызывать как а, так и б, даже если результат вызова а ложен и, следовательно, известен как ложный, независимо от результата вызова б.
Такая же разница существует для || и | операторы.
В некоторых языках есть интересные ситуации, когда выражения выполняются в другом порядке. Я имею в виду именно Ruby, но уверен, что они позаимствовали его из других источников (вероятно, Perl).
Выражения в логике останутся слева направо, но, например:
puts message unless message.nil?
Вышеупомянутое будет оценивать "message.nil?" сначала, затем, если он оценивается как ложный (если только это не похоже на if, за исключением того, что он выполняется, когда условие ложно, а не истинно), будет выполняться «помещает сообщение», которое выводит содержимое переменной сообщения на экран.
Иногда это интересный способ структурировать код ... Мне лично нравится использовать его для очень коротких 1 лайнеров, как показано выше.
Редактировать:
Чтобы было немного понятнее, приведенное выше то же самое, что:
unless message.nil?
puts message
end
Нет, по крайней мере, компилятор C# не работает в обратном направлении (в && или ||). Это слева направо.
What is a good example of when to use the bitwise operator instead of the "short-circuited boolean"?
Предположим, у вас есть флаги, скажем, для атрибутов файлов. Предположим, вы определили READ как 4, WRITE как 2 и EXEC как 1. В двоичном формате это:
READ 0100
WRITE 0010
EXEC 0001
Каждый флаг имеет один набор битов, и каждый из них уникален. Побитовые операторы позволяют комбинировать эти флаги:
flags = READ & EXEC; // value of flags is 0101
@shsteimer
The concept modesty is referring to is operator overloading. in the statement: ... A is evaluated first, if it evaluates to false, B is never evaluated. The same applies to
Это не перегрузка оператора. Перегрузка оператора - это термин, который позволяет вам определять настраиваемое поведение для операторов, например *, +, = и т. д.
Это позволит вам написать свой собственный класс «Журнал», а затем выполнить
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
на самом деле называется Оценка короткого замыкания
Вы используете &, когда вы специально хотите оценить все подвыражения, скорее всего, потому, что они имеют побочные эффекты, которые вы хотите, даже если конечный результат будет ложный и, следовательно, не выполнить вашу часть тогда вашего если-оператора.
Обратите внимание, что & и | работает как для побитовых масок, так и для логических значений, а не только для побитовых операций. Они побитовые называется, но они определены как для целых, так и для логических типов данных в C#.
Когда все в порядке, они выполняются слева направо.
Когда вещи вложены, они выполняются от внутреннего к внешнему. Это может показаться запутанным, поскольку обычно то, что «самое внутреннее» находится в правой части строки, поэтому кажется, что оно идет в обратном направлении ...
Например
a = Foo( 5, GetSummary( "Orion", GetAddress("Orion") ) );
Бывает так:
GetAddress с буквальным "Orion".GetSummary с буквальным "Orion" и результатом GetAddressFoo с буквальным 5 и результатом GetSummaryaЯ понимаю, что на этот вопрос уже был дан ответ, но я хотел бы добавить еще немного информации, относящейся к этой теме.
В языках, таких как C++, где вы можете фактически перегрузить поведение && и || операторов, настоятельно рекомендуется использовать не делай этого. Это связано с тем, что, когда вы перегружаете это поведение, вы в конечном итоге заставляете оценивать обе стороны операции. Это делает две вещи:
Для получения дополнительной информации прочтите книгу Скотта Мейерса Более эффективный C++. Ваше здоровье!
Мне нравятся ответы Ориона. Я добавлю две вещи:
Допустим, у нас есть следующий пример:
a = Foo(5, GetSummary("Orion", GetAddress("Orion")),
GetSummary("Chris", GetAddress("Chris")));
Вот порядок исполнения:
GetAddress("Orion")GetSummary("Orion", ...)GetAddress("Chris")GetSummary("Chris", ...)Foo(...)aЯ не могу говорить о юридических требованиях C# (хотя я тестировал аналогичный пример с использованием Mono перед написанием этого сообщения), но этот порядок гарантирован в Java.
И просто для полноты (поскольку это также независимый от языка поток), существуют такие языки, как C и C++, где порядок не гарантируется, если нет точки последовательности. Ссылки: 1, 2. Однако, отвечая на вопрос потока, && и || являются точками последовательности в C++ (если они не перегружены; также см. Отличный ответ OJ). Итак, несколько примеров:
foo() && bar()foo() & bar()В случае &&foo() гарантированно запускается до bar() (если последний запускается вообще), поскольку && является точкой последовательности. В случае & такая гарантия не предоставляется (в C и C++), и действительно, bar() может работать до foo() или наоборот.
«C#: слева направо, и обработка останавливается, если найдено совпадение (истинно)».
Зомби-овца ошибается, недостаточно репутации, чтобы проголосовать против.
Вопрос в операторе &&, а не в || оператор.
В случае && оценка остановится, если будет найдено ЛОЖЬ.
В случае || оценка останавливается, если обнаруживается ИСТИНА.
Ага. Вы совершенно правы. Однако я очень надеюсь, что мой первоначальный ответ был истолкован правильно. Конечно, я не собирался никого вводить в заблуждение.
It was asked in a followup why or when would anyone use And instead of AndAlso (or & instead of &&): Here is an example:
if ( x.init() And y.init()) then x.process(y) end y.doDance()In this case, I want to init both X and Y. Y must be initialized in order for y.DoDance to be able to execute. However, in the init() function I am doing also some extra thing like checking a socket is open, and only if that works out ok, for both, I should go ahead and do the x.process(y).
Я считаю, что это довольно сбивает с толку. Хотя ваш пример работает, это не типичный случай использования And (и я бы, вероятно, написал это по-другому, чтобы было понятнее). And (& на большинстве других языков) на самом деле является побитовой операцией «И». Вы могли бы использовать его для вычисления битовых операций, например, удаления бита флага или флагов маскирования и тестирования:
Dim x As Formatting = Formatting.Bold Or Formatting.Italic
If (x And Formatting.Italic) = Formatting.Italic Then
MsgBox("The text will be set in italic.")
End If
Язык программирования D позволяет оценка слева направо с коротким замыканием и не допускать перегрузку операторов && и "||".
Как заявляли другие, замыкание на оператор && происходит на ложный.