2013-12-21 2 views
0
class Program 
{ 
    static void Main(string[] args) 
    { 
    bool success = true; 
    int[] array = { 10, 15, 20 }; 
    foreach (var i in array) 
    success = success && SynchronizeAccount(i); 
    } 

    static bool SynchronizeAccount(int i) 
    { 
    Console.WriteLine(i); 
    return false; 
    } 
} 

Выход равен 10. После первого шага «успех» становится ложным и никогда не будет истинным, поэтому C# прекратит выполнение цикла после первой итерации. Но мне нужен эффект SIDE SynchronizeAccount, а не «успех».Boolean AND не оценивает обе стороны выражения

+9

Скорее всего, будет ошибкой в ​​вашей логике, чем ошибка в компиляторе. –

+0

@GrantWinney нет, это определенно ошибка в компиляторе;) – MichaC

+1

Итак, вы действительно думаете, что обнаружили ошибку в компиляторе, да? Выигрывать миллион долларов в лотерею, даже не купив состояние, более вероятно. –

ответ

17

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

Переверните операнды или измените их на success & SynchronizeAccount, чтобы заставить оценить оба операнда.

Обратите внимание, что это уникальная особенность C#, который можно применять как & и && для булевых значений - в большинстве других языков, включая Java и PHP один амперсанд (&) является побитовое И, что часто дает совершенно разные результаты.

+0

Правильное объяснение различия между 'success && SynchronizeAccount' и' success & SynchronizeAccount'. Обратите внимание, что также возможно использовать составное назначение в исходном вопросе, поэтому 'success & = SynchronizeAccount;'. –

8

Это не ошибка, это нормальное поведение. && operator будет оценивать только правую сторону оператора, если левая сторона вычисляться true:

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

Таким образом, после первой итерации, success вычисляет false и SynchronizeAccount не дозвонились снова.

Если вы хотите оценить SynchronizeAccount независимо от того, что она возвращает, используйте & operator вместо:

foreach (var i in array) 
    success = success & SynchronizeAccount(i); 

или более просто:

foreach (var i in array) 
    success &= SynchronizeAccount(i); 

Или, возможно, использовать немного Linq:

bool success = array.Aggregate(true, (b, i) => b & SynchronizeAccount(i)); 
4

Это не ошибка, это называется Short-circuit evaluation. Если вам действительно нужно, чтобы второй способ работал тоже, мы & вместо &&

1

Я бы не рассматривал это как ошибку; это просто оптимизация. «& &» - это короткое замыкание, поэтому компилятору разрешено оптимизировать вызов метода, если его результат не требуется.

Вы можете попробовать переписывания это как


foreach (var i in array) { 
    if(!SynchronizeAccount()) 
    success = false; 
} 
+1

Не только разрешено оптимизировать, это необходимо. Например, если я говорю «if (x! = Null && x.IsNew) {...}', требуется, чтобы правая часть оператора '&& была *** не *** оценена, если левая -hand сторона 'false' (оценка правой части в этом случае приведет к исключению). –

+0

@ JeppeStigNielsen вы совершенно правы; но я ответил на слова «stop loop execution». Это может быть просто мнение о старте, но если задание «успех» является единственным действием в теле цикла, компилятор может оптимизировать его с остановкой всего цикла. Это не изменяет никакого видимого результата, кроме, возможно, потраченного времени. – Netch

1

Рассмотрите возможность удаления success из вашего цикла.

Другие ответы являются прекрасными для объяснения & против &&, но я не уверен, в чем цель success даже в вашем коде.Так как вы намерены игнорировать его и перебирать все элементы в array в любом случае, просто позвоните SynchronizeAccount в свой цикл foreach и проигнорируйте возвращаемое значение.

static void Main(string[] args) 
{ 
    int[] array = { 10, 15, 20 }; 
    foreach (var i in array) 
     SynchronizeAccount(i); 
} 
Смежные вопросы