2011-09-06 2 views
20

오늘 초에 메소드를 코딩 할 때 내가 구현하는 관용구가 왜 컴파일을 수행하는지 정확히 알지 못한다는 사실을 알게되었습니다. 다른 모든 멀리 추상화되는 경우는 다음과 같이 보일 것입니다 :.NET에서 명시 적으로 무한 루프가 특별한 경우로 처리됩니까?

private int Example() 
    { 
     while (true) 
     { 
      if (some condition) 
      { 
       return 1; 
      } 
     } 
    } 

당신은 명시 적으로 무한 루프, 루프는 return 문으로 종료 될 루프 내부 조건의 일부 설정이있다. 대답은 복잡하고 관련이 없기 때문에 while 절에서 종료 조건을 검사하는 것과는 대조적으로이 작업을 수행하는 시간을 무시해 봅시다. 제가 알고 싶은 것은 컴파일러가 "Not 모든 경로는 값을 반환합니다. " 오류, 엄격히 말해서 모든 경로가 값을 반환하지는 않습니다. while 루프가 입력되지 않는 경우 (물론 결코 발생하지 않음) 아무 것도 반환하지 않습니다.

이제 상황이 상상할 수있는 두 가지 이유가 있습니다. 이것은 다른 이유로 인해 발생하는 최적화의 부작용이거나이 경우에이 사례를 명시 적으로 컴파일러에서 처리하는 것입니다. 나의 본능은 그것이 아마도 첫 번째 사건이라는 것이다. 컴파일러는 경우에 일정한 사실을보고하고, 조건 멀리 최적화

private int Example2() 
{ 
    if (true) return 1; 
} 

때문에 : 그것은이 컴파일 것으로, 예를 들어, 모든 나를 놀라게하지 않습니다. 나는 이것이 왜 첫 번째 예제를 "고칠 것인가"하는 이유를 알지 못합니다. 루프를 제거한다 약간의 최적화가 플레이에있는 경우

아, 그리고 훨씬 더 이상하게,이 컴파일 :

private int Example3() 
    { 
     while (true) 
     { 
      if (false) 
      { 
       return 1; 
      } 
     } 
    } 

나는 전체 내부 루프는 제거하기, 멀리 최적화 될 것이라고 생각 모든 유효한 반환. 이것이 바이트 코드/컴파일러 레벨에서 실제로 무엇이 일어나고있는가?

+1

: 따라서 C# 컴파일러 (가하지 않는 프로그램을 허용하지 않습니다하지만) 항상 값을 반환에 대한 코드를 불평 할 수 그들이 무엇을하고 있는지 아십시오 ..... "* – ChaosPandion

+0

+1 결코 이런 상황을 생각하지 못했습니다. – Arun

답변

29

메서드의 끝이 에 도달 할 수 없으므로 컴파일러에서 플래그를 지정하지 않습니다.입니다. 이것은 문제가 아닙니다. 값을 반환하지 않고 메서드의 끝 (닫는 중괄호)에 도달 할 수 있다면 문제가됩니다.

이 컴파일러 최적화의 문제가 아니다 - 그것은 사양에 규정 도달에 대한 정의를 다음의 경우입니다. 당신이 모든 return 문이 필요하지 않습니다

참고 ...이 코드는 쓸모없는,하지만 완벽하게 유효합니다

public int EndlessLoop() 
{ 
    while (true) 
    { 
    } 
} 
+1

빛을 "도달 가능성"으로 가져 오는 +1! – Arun

+2

컴파일러 개발자 중 한 명인 Eric Lippert는 궁금한 점이 있으면 도달 가능성에 대해 블로그에 올렸습니다. http://blogs.msdn.com/b/ericlippert/archive/tags/reachability/ –

3

당신에게 무한 루프의 이러한 종류의 사용 사례를 제공하기 위해, 고려 다음 코드를

public int KeyboardChecker() 
{ 
    while (true) 
    { 
     if (KeyHasBeenPressed()) 
     { 
      HandleKeyPress(); 
     } 
    } 
} 

그런 다음하여 비동기 적으로 키보드 입력을 처리하는, 자신의 스레드에서이 방법을 실행 (이 폴링 패턴 대신에 이벤트 시스템을 가지고는 일반적으로 바람직하다).

스레드가 완료되면 스레드가 상태 코드를 반환한다고 생각할 수 있으므로 메서드의 반환 값은 int입니다. 그러나이 특정 스레드는 절대로 끝나지 않으므로 메서드에 return 문이 포함되어 있지 않은 것이 전혀 문제가되지 않습니다. C# 디자이너는 이러한 유스 케이스에 대해 알고 있었고 위의 메서드를 합법적으로 만들었습니다.

특정 메서드가 항상 값을 반환하는지 결정하는 일반적인 문제는 결정할 수 없다 (즉, 어떤 컴퓨터 프로그램으로도 해결할 수 없음). 나는 그들이 희망 "* 내가 마지막 예를 말 컴파일러의 경우라고 생각

public int DoWork() 
{ 
    // The compiler doesn't figure out this will always be true. 
    if (((int)Math.Sqrt(4)) == 2) 
    { 
     return 3; 
    } 
    // And therefore complains that not all code paths return a value for this method. 
} 
관련 문제