2013-12-21 6 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입니다. 첫 번째 단계 후 'success'가 false가되고 절대로 true가되지 않으므로 C#이 첫 번째 반복 이후 루프 실행을 중지합니다. 하지만 SynchronizeAccount의 SIDE 효과가 필요합니다. '성공'값이 아닙니다.부울 AND 식의 양쪽을 평가하지 않습니다.

+9

논리에 결함이있는 것보다 컴파일러의 버그가 더 많습니다. –

+0

@GrantWinney 아니요, 컴파일러의 버그입니다.) – MichaC

+1

정말 컴파일러에서 버그를 발견했다고 생각하십니까? 행운을 구입하지 않고도 복권에 백만 달러를 얻는 것이 더 쉽습니다. –

답변

17

거의 모든 프로그래밍 언어 에서처럼 C#은 &&을 지연 평가합니다 - 왼쪽 피연산자가 이미 거짓이면 전체 표현식이 절대로 참일 수 없으므로 더 이상 표현식의 오른쪽 피연산자를 평가할 필요가 없습니다 .

두 피연산자의 평가를 강제하려면 피연산자를 뒤집거나 success & SynchronizeAccount으로 변경하십시오. 자바와 PHP 하나의 앰퍼샌드 (&)를 포함한 대부분의 다른 언어로 종종 완전히 다른 결과를 제공하는 비트 AND는 - 그것은 당신이 부울 값으로 모두 &&&을 적용 할 수 있습니다 C 번호의 고유 한 기능이 있다는

참고.

+0

'success && SynchronizeAccount'와'success & SynchronizeAccount'의 차이에 대한 정확한 설명. 원래 질문에서 복합 할당을 사용할 수도 있습니다. 따라서'success & = SynchronizeAccount;'. –

8

이것은 버그가 아니며 정상적인 동작입니다.

조건부 AND 연산자 (& &)는이 논리 AND의 부울 오퍼랜드 있지만 번째 피연산자를 평가 수행 좌측이 true로 평가되는 경우 && operator은 오퍼레이터의 우측을 평가할 것이다 필요하다면.

그래서 첫 번째 반복 한 후, successfalse로 평가하고, SynchronizeAccount는 다시 호출되지 않습니다. 조금 Linq에를

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

을 아니면 사용합니다 : 더 간단하게

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

또는를 : 당신이 상관없이 반환 무엇 SynchronizeAccount을 평가하려면

대신 & operator를 사용

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

이것은 버그가 아니며, 이라고합니다.. 두 번째 방법도 실제로 작동해야하는 경우 대신 &을 입력하십시오.

1

버그로 처리하지 않습니다. 그것은 단순히 최적화와 같이 보입니다. "& &"은 단락이므로 컴파일러는 결과가 필요하지 않은 경우 메서드 호출을 최적화 할 수 있습니다.

이 같은


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

최적화가 가능할뿐만 아니라 필수 사항입니다. 'if (x! = null && x.IsNew) {...}'와 같이 말하면'&& '연산자의 오른쪽은 ***이 아닌 경우 ***이 평가되어야합니다. - hand 측은'false' (오른쪽면을 평가하면 예외가 발생합니다). –

+0

@JeppeStigNielsen 당신이 맞습니다; 하지만 "루프 실행 중지"라는 단어에 응답했습니다. 단순히 주제의 시발점 의견 일 수도 있지만 "성공"설정이 루프 본문에서 유일한 동작 인 경우 컴파일러는 전체 루프를 중지하여 최적화 할 수 있습니다. 아마, 보냈던 시간을 제외하고는 눈에 보이는 결과는 변하지 않습니다. – Netch

1

는 루프에서 success를 제거하는 것이 좋습니다 재 작성 시도 할 수 있습니다.

&&&을 설명하는 데는 다른 답변이 필요합니다. 그러나 어떤 목적으로 코드에 success이 있는지 모르겠습니다. 어쨌든 이것을 무시하고 모든 항목을 반복 할 예정이므로 foreach 루프 내에 SynchronizeAccount을 호출하고 반환 된 값을 무시하십시오.

static void Main(string[] args) 
{ 
    int[] array = { 10, 15, 20 }; 
    foreach (var i in array) 
     SynchronizeAccount(i); 
}