2009-10-29 2 views
18

상대적인 초보자로서 가능한 한 많은 코드를 테스트하고 쓸 수있는 한 많은 것을 읽으려고합니다. 나는 Jons Brainteasers (질문 # 2) 중 하나를보고 있었고 나의 결과물은 대답과 달랐습니다. 어느 것이 최근 버전에서 어떤 것이 바뀌 었는지 물어보고 다른 사람들이이 코드에서 얻는 결과를 확인하기 위해 여기로 왔습니다.정적 생성자 (Jon Skeet Brainteaser) 사용

질문은 "무엇이 표시되고, 왜, 어떻게 자신감이 있습니까?"입니다.

using System; 

class Foo 
{ 
    static Foo() 
    { 
     Console.WriteLine ("Foo"); 
    } 
} 

class Bar 
{ 
    static int i = Init(); 

    static int Init() 
    { 
     Console.WriteLine("Bar"); 
     return 0; 
    } 
} 

class Test 
{ 
    static void Main() 
    { 
     Foo f = new Foo(); 
     Bar b = new Bar(); 
    } 
} 

무엇이 있다면 우리는 서로 다른 답변을 얻을 수 있습니까?

+1

"최근 버전의 Visual Studio에서 변경된 사항이 있는지 묻습니다." 새로운 버전의 .NET Framework에서 변경된 사항이 있다면 실제로 묻는 것입니다. 그리고 메이저는 버전에서 버전으로 바뀌지 않을 것입니다. 주요 변경 사항이 될 것이기 때문입니다. –

+1

중복 됨. 흥미 롭 군. –

+3

글쎄, 네가 얻고있는 대답은 뭐지? –

답변

24

지금

내가 디버거없이와/다른 결과를 얻을 수 ;-p 디버거 외부에서 릴리스 모드에서 그것을 시도. 디버거는 미묘한 뉘앙스/최적화를 혼란에 빠뜨립니다. 따라서 디버거가 중요한 부분 중 하나라고 추측 할 수 있습니다. 디버그를 더 어렵게 만듭니다 -p

+1

정확히 내가 누락 된 부분입니다. –

+1

릴리스 모드에서는 'Foo', 디버그 모드에서는 'Foo'and'Bar'가 표시됩니다. 원시 프로그래밍 언어의 관점에서 보면 'Foo'와 'Bar'가 순서대로 표시되어서는 안됩니까? –

6

존 자신의 answers page이 이에 대해 설명합니다. 나는 C# 녀석이 아니지만 시스템이 정적 foo 코드를 호출 할 때 (따라서 "Foo"라고) 언제 호출 할 지 정확히 하나의 선택을 가지고있는 것처럼 보입니다. 그러나 초기화 할 때 기본적으로 무한한 자유를 결정합니다. Bar.i "Bar") 클래스가로드 될 때 또는 처음 사용될 때 또는 전혀 사용되지 않을 때 발생할 수 있습니다.

0

그냥 "FooBar"가 아닌 다른 것을 표시하면 놀랄 것입니다.

Foo에 먼저 액세스하기 때문에 정적 생성자가 실행됩니다. 막대를 인스턴스화 할 때 정적 필드 초기화 프로그램이 계속됩니다.

해피가 되길 바랍니다.

4

디버그 모드에서 Foo, Bar, 릴리스 모드에서 Bar, Foo를 인쇄합니다. 따라서 릴리스 코드가 최적화되고 최적화로 인해 Bar가 먼저 호출됩니다. 그러나 항상 이 없으므로 보증이 적용됩니다.

+1

최적화 원인 표시 줄이 먼저 호출되는 이유는 무엇입니까? 여기 규칙은 무엇입니까? –

+0

내가 확인해야 할 것이지만, 디버거라면 디버그/릴리스 이상으로 놀라지 않을 것이다. 그것은 정기적으로합니다. –

+2

bar에는 정적 생성자가 없으므로 i의 값을 초기화하고 Bar 클래스를 미리 준비 할 수 있습니다. 이렇게하면 나중에 더 많은 작업이 수행되지 않습니다. 또는 디버거를 사용하여 Bar를 나중에 초기화 할 수 있습니다.Foo는 생성자를 가지고 있기 때문에 처음 생성 될 때 항상 초기화되고 Bar는 언제든지 초기화 될 수 있습니다. –

0

나는 foo bar가 인쇄 될 것이라고 생각합니다. 정적 유형 생성자는 Foo에서 먼저 실행될 것이고 Init 메소드는 Bar 클래스에서 호출 될 것입니다. 나는 행동이 변할 수 있는지 여부에 대해 모른다. 이건 재미 있네.