>

다음 코드 줄이 컴파일러 경고를 생성하지 않는 이유는 무엇입니까?

void Main()
{
  throw new Exception();
  throw new Exception();
}

알다시피, 컴파일러는 두 번째 throw 예외에 도달 할 수 없음을 알려줘야합니다.


  • 답변 # 1

    이것은 분명히 컴파일러 버그이며, C # 3.0에서 소개되었습니다. 접근성 검사기를 크게 리팩터링 한 시점입니다. 이건 아마 내 잘못이야, 미안해.

    버그는 완전히 양성이다;기본적으로 경고 리포터에서 사례를 잊어 버렸습니다. 도달 가능성 정보를 올바르게 생성합니다. 다른 사람들이 지적했듯이 codegen 전에 도달 할 수없는 코드를 올바르게 잘라냅니다.

    버그는 경고 생성기에서 누락 된 사례 일뿐입니다. 우리는 코드의 일부를 도달 할 수 없게 만들 때 심각한 경고를보고하지 않도록 까다로운 코드가 있습니다. 컴파일러에는 무조건 고토 ( "goto", "break", "continue"), 조건부 고토 ( "if", "while"등), try-catch-finally (동등한 양식 포함)에 대한 경고를 구체적으로보고하는 코드가 있습니다. 잠금 및 사용과 같은 마지막으로 catch-catch-finally, 블록, 리턴 (수율 리턴 및 정규 리턴), 로컬 선언, 레이블이있는 명령문, 스위치 및 표현식 명령문.

    해당 목록에 "투표"가 보입니까? 나도 우리가 잊었 기 때문입니다.

    불편을 드려 죄송합니다. 품질 관리에 메모를 보내면 향후 버전의 언어로이 문제를 해결할 수 있습니다.

    이 점에주의를 기울여 주셔서 감사합니다.

  • 답변 # 2

    컴파일러에게 경고/오류를 줄 수 있지만 슬프게도 그렇지 않습니다. 그러나 IL 코드를 보면 첫 번째 예외 만 고려됩니다. connect.microsoft.com에 로그인하여보고 싶은 것으로 올릴 수 있습니다.

    아래 코드를 ILDasm하면

    static void Main(string[] args)
            {
                Console.Write("Line 1");
               throw new Exception(); 
               throw new Exception();
               Console.Write("Line 4");
            }
    
    

    이것을 얻을 것이다

    .method private hidebysig static void  Main(string[] args) cil managed
    {
      .entrypoint
      // Code size       18 (0x12)
      .maxstack  8
      IL_0000:  nop
      IL_0001:  ldstr      "Line 1"
      IL_0006:  call       void [mscorlib]System.Console::Write(string)
      IL_000b:  nop
      IL_000c:  newobj     instance void [mscorlib]System.Exception::.ctor()
      IL_0011:  throw
    } // end of method Program::Main
    
    

    첫 번째 Exception 객체 이후에 다른 것은 IL로 변환되지 않습니다.

  • 답변 # 3

    Lippert가 위에서 언급 한 것처럼이 버그는 이상한 결과를 초래합니다. 물론 이와 같은 코드는 컴파일 타임 경고를 제공하지 않습니다.

    static int Main()
    {
      return 0;
      throw new Exception("Can you reach me?");
    }
    
    

    창의적이라면 여전히 throw 를 만들 수 있습니다  진술은 (관련되지 않은) 경고를 유발합니다. 이 흥미로운 예에서 "green"에 도달 할 수없는 경우에만 코드가 경고를 생성합니다.

    static int Main()
    {
      return 0;
      throw new Exception(((Func<string>)(() => { if (2 == 2) { return "yellow"; } return "green"; }))());
    }
    
    

    (코드는 람다에서 델리게이트 인스턴스를 생성하고 델리게이트를 호출 함)

    그러나이 예제는 더 단순하고 더 나빠 보입니다 :

    static int Main()
    {
      int neverAssigned;
      return 0;
      throw new Exception(neverAssigned.ToString());
    }
    
    
    이 마지막 코드 샘플도 경고없이 컴파일됩니다! neverAssigned "사용"에는 문제가 없습니다  "사용법"에 접근 할 수 없기 때문입니다. 그러나 로컬 변수에 할당되지 않은 ( "실제로"읽히지 않은) 변수에 대한 경고도 표시되지 않습니다. 다시 말하지만 전혀 경고하지 않습니다. 매우 잘못된 것 같습니다.

    향후 버전의 Visual C #에서이 동작이 변경 될지 궁금합니다. 그것을 바꾸면 사람들은 예전에는 없었던 경고를받을 수 있습니다 (제 생각에 그들은 가치가 있습니다).

    추가 :이 동작은 Visual Studio 2015의 Roslyn 기반 C # 6.0 컴파일러에서 변경되지 않은 것으로 보입니다.

  • 이전 database - postgresql 경고 - "더티 데이터를 플러시 할 수 없습니다 : 기능이 구현되지 않았습니다"
  • 다음 c# - JavaScriptSerializer ()를 사용하여 JSON 파일 역 직렬화