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 ]

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

Нет, по крайней мере компилятор C # не работает в обратном направлении (в && или ||). Это слева направо.

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

Когда все в строке, они выполняются слева направо.

Когда вещи вложены, они выполняются изнутри наружу. Это может показаться странным, так как обычно то, что «внутреннее» находится с правой стороны линии, так что кажется, что оно движется назад ...

Например

a = Foo( 5, GetSummary( "Orion", GetAddress("Orion") ) );

Вещи случаются так:

  • Звоните GetAddress с буквальным "Orion"
  • Вызовите GetSummary с литералом "Orion" и результатом GetAddress
  • Звоните Foo с литералом 5 и результатом GetSummary
  • Присвойте это значение a
1 голос
/ 08 августа 2008

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

Предположим, у вас есть флаги, скажем, для атрибутов файла. Предположим, вы определили READ как 4, WRITE как 2 и EXEC как 1. В двоичном коде это:

READ  0100  
WRITE 0010  
EXEC  0001

Каждый флаг имеет один бит, и каждый уникален. Битовые операторы позволяют комбинировать эти флаги:

flags = READ & EXEC; // value of flags is 0101
1 голос
/ 08 августа 2008

Мне нравятся ответы Ориона. Я добавлю две вещи:

  1. Слева направо по-прежнему применяется первым
  2. Внутренний-внешний, чтобы все аргументы были разрешены перед вызовом функции

Скажем, у нас есть следующий пример:

a = Foo(5, GetSummary("Orion", GetAddress("Orion")),
           GetSummary("Chris", GetAddress("Chris")));

Вот порядок исполнения:

  1. GetAddress("Orion")
  2. GetSummary("Orion", ...)
  3. GetAddress("Chris")
  4. GetSummary("Chris", ...)
  5. Foo(...)
  6. Назначает a

Я не могу говорить о юридических требованиях C # (хотя я тестировал подобный пример с использованием Mono перед написанием этого поста), но этот порядок гарантирован в Java.

И просто для полноты (поскольку это также не зависящий от языка поток), существуют языки, такие как C и C ++, где порядок не гарантируется, если нет точки последовательности. Список литературы: 1 , 2 . Однако, отвечая на вопрос потока, && и || являются точками последовательности в C ++ (если не перегружены; также см. Отличный ответ OJ). Вот несколько примеров:

  • foo() && bar()
  • foo() & bar()

В случае && гарантированно будет выполняться foo() до bar() (если последний вообще выполняется), поскольку && является точкой последовательности. В случае & такая гарантия не предоставляется (в C и C ++), и действительно, bar() может работать до foo() или наоборот.

0 голосов
/ 15 апреля 2010

Язык программирования D Выполняет оценку слева направо с коротким замыканием , а не допускает перегрузку && и '||' операторов.

0 голосов
/ 20 августа 2008

@ csmba

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

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

В этом случае я хочу инициализировать оба X и Y. Y должен быть инициализирован, чтобы y.DoDance мог выполняться. Тем не менее, в функции init () я также делаю некоторые дополнительные вещи, такие как проверка, открыт ли сокет, и только если это работает нормально, для обоих я должен продолжить и выполнить 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
0 голосов
/ 08 августа 2008

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

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

Вы используете &, когда вы специально хотите оценить все подвыражения, скорее всего потому, что они имеют побочные эффекты, которые вы хотите, даже если конечный результат будет false и, следовательно, не выполнит ваши затем часть вашего , если -общение.

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

...