2009-04-02 2 views
18

생성자가 호출되기 전에 정적 필드 초기화가 완료되어야합니까?C#에서 정적 필드 초기화는 어떻게 작동합니까?

다음 프로그램은 나에게 잘못된 것처럼 보이는 출력을 제공합니다.

new A() 
_A == null 
static A() 
new A() 
_A == A 

코드 :

public class A 
{ 
    public static string _A = (new A()).I(); 

    public A() 
    { 
     Console.WriteLine("new A()"); 
     if (_A == null) 
      Console.WriteLine("_A == null"); 
     else 
      Console.WriteLine("_A == " + _A); 
    } 

    static A() 
    { 
     Console.WriteLine("static A()"); 
    } 

    public string I() 
    { 
     return "A"; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var a = new A(); 
    } 
} 

답변

22

이 올바른 것입니다.

정적 초기화 후 정적 생성자는 표준 생성자 전에 실행되지만,이 실행될 때, 그것은 그래서 당신의 비 정적 생성자 경로를 통해 전달 새로 만들기()를 사용합니다. 이로 인해 사용자가 보는 메시지가 표시됩니다.

다음은 실행의 전체 경로입니다 :

당신이 당신의 프로그램에서 첫 번째 호출 var a = new A();, 이것은 액세스 할 때 처음

. 이것은이 시점에서 A._A

의 정적 초기화를 실행됩니다

, A._A 이것은


Console.WriteLine("new A()"); 
if (_A == null) 
    Console.WriteLine("_A == null");   

안타 _A = (new A()).I();

이 시점에서, _A가되지 않았기 때문에 구축 반환 된 생성 된 유형 (아직)으로 설정합니다.

다음으로, 정적 생성자 A { static A(); }가 실행됩니다. 그러면 "정적 A()"메시지가 인쇄됩니다.

마지막으로, 원래의 문 ( var a = new A();)을 실행하지만,이 시점에서, 정적이 구성된다, 그래서 당신은 최종 인쇄를 얻을.

+0

Dang! 나를 때려! –

+0

모든 점에서 ... 정적 생성자가 먼저 실행되지 않습니다. 정적 필드 초기화 프로그램이 먼저 실행됩니다. – Prankster

+1

A._A의 생성은 정적 생성자에서 발생합니다. 컴파일러가 정적 생성자 (.cctor)의 모든 필드 초기화를 C# 정적 생성자로 선언 된 코드 앞에 추가한다는 것입니다. –

-1

예, 생성자가 호출되기 전에 정적 필드 초기화가 완료되어야합니다. 하지만 컴파일러를 비정상적인 상황에 놓는다면이 규칙을 지킬 수 없습니다.

이 재미있는 트릭이지만, 거 일반 응용 프로그램에서 일이 아닙니다.

1

저는 실제로 그것이 당신이 생각하는 것을하고 있다고 생각합니다. 당신의 시험은 말하기 어렵게 만듭니다. _A

public static string _A = (new A()).I(); 

첫 번째는 새로운 인스턴스를 생성하기위한

귀하의 initalization, 새로운 A()와 _A = NULL의 따라서 귀하의 글. 그것이 시작되었을 때 null 이었기 때문에 이것은 초기화입니다. 초기화 된 후에는 새 인스턴스를 반환하는 정적 생성자가 호출됩니다.

0

컴파일러가 예상 한 것처럼 보입니다.

1 - 모든 정적 코드는 클래스 (필드 첫째, 다음 정적 생성자) 실행 : - 클래스의 생성자를 호출

public static string _A = (new A()).I(); 

// and 

static A() 
{ 
    Console.WriteLine("static A()"); 
} 

2가 :

public A() 
{ 
    Console.WriteLine("new A()"); 
    if (_A == null) 
     Console.WriteLine("_A == null"); 
    else 
     Console.WriteLine("_A == " + _A); 
} 

당신은 질문 왜 이것이 가능한지. 글쎄, 내 의견으로는 인스턴스가 모든 클래스 변수가 생성시 초기화된다는 것을 절대적으로 요구하지는 않는다. 단지 존재해야만합니다. 모든 정적 초기화가 완료되기 전에 인스턴스가 만들어지기 때문에이 특별한 경우는이 생각을 지원한다고 생각합니다.

0

한 별도의 보조 노트 -는 C# 사양 (I 4.0 찾고 있어요,하지만 너무 3.0에있다)라고 10.5.5.1 정적 필드 초기화에서 :

하면 정적 생성자 (§10.12) 이 클래스에 있으면 정적 필드 초기화 프로그램을 실행하면 정적 생성자를 실행하기 직전에 이 발생합니다. 그렇지 않은 경우 정적 필드 초기화 프로그램은 해당 클래스의 정적 필드를 처음 사용하기 전에 구현 - 의존 시간 인 에서 으로 실행됩니다.

정적 생성자가 있으므로 "otherwise"절이 적용되지 않습니다. 하지만 정적 생성자가없는 경우 정적 필드 초기화 프로그램을 '구현 종속 시간에'실행할 수 있다는 것을 아는 것이 관련 정보라고 생각합니다. 정적 필드 이니셜 라이저가 정적 필드 자체에 액세스하지 않고 의존하는 일부 유형의 데이터 초기화 또는 개체 생성을 수행하는 경우 문제가 될 수 있습니다.

그것은 수수께끼 같았습니다.하지만 적어도 구현에 의존하는 시간이 C# 3.0과 4.0 사이에서 변경된 것처럼 보였습니다. 적어도 필자가보고있는 상황에서 보았습니다. 쉬운 솔루션은 간단합니다. 정적 인 생성자를 추가하면됩니다.

관련 문제