2011-06-11 4 views
3

.NET 클래스 로더가 작동하는 표준 방법이 있습니까?.NET 클래스 로더가 작동하는 표준 방법이 있습니까?

Option Strict On : Option Explicit On 

Module Module1 
    Sub Main() 
     System.Diagnostics.Debug.WriteLine("Main") 
     Dim g = C.A 
    End Sub 
End Module 

Public Class C 
    Shared Sub New() 
     System.Diagnostics.Debug.WriteLine("Init C") 
    End Sub 
    Shared Property A As New A 
End Class 

Public Class A 
    Shared Sub New() 
     System.Diagnostics.Debug.WriteLine("Init A") 
    End Sub 
    Public Sub New() 
     System.Diagnostics.Debug.WriteLine("A Constructor") 
    End Sub 
End Class 

나는 다음과 같은 출력이 (모든 구현 된 플랫폼에서) 컴파일 된 코드는 것입니다 보장 할 수 있습니다 :

는이 코드를 컴파일 말해봐?

Main 
Init A 
A Constructor 
Init C 
+2

"클래스 로더"는 다른 것을 의미합니다. 당신은 일명 "정적 생성자"인 "클래스 이니셜 라이저"에 대해 이야기하고 있습니다. –

+0

Jon Skeet이 형식 초기화 (일부 .NET 4 변경 사항 포함)에 대해 설명합니다. http://msmvps.com/blogs/jon_skeet/archive/2010/01/26/type-initialization-changes-in-net-4-0. aspx – Govert

+0

@Hans : 아마도 그렇지만 런타임 클래스 로더가 특정 시간에 * type initializer *를 호출 할 수 있는지 여부를 궁금해하는 것도 합리적입니다. (사실, 클래스 로더가'beforefieldinit'라고 표시된 타입에 대해서만 그렇게하는 것은 합당합니다. 그렇지 않다면, * 타입 이니셜 라이저는 나중에 spec에서 지시 된대로 호출되어야합니다.) –

답변

4

VB 컴파일러는 인라인 초기화가 아닌 생성자를 사용하기 때문에 beforefieldinit 형식을 표시하지 않으며 순서가 정확하게 제어됩니다.

는 경우, 그러나, 다음 (사용 인라인 초기화)를 썼다 :

Option Strict On : Option Explicit On 

Module Module1 
    Sub Main() 
     System.Console.WriteLine("Main") 
     Dim g = C.A 
    End Sub 
End Module 
Public Class C 
    Shared Function Narg() As A 
     Dim alpha As New A 
     System.Console.WriteLine("Init C") 
     Return alpha 
    End Function 
    Shared Property A As A = Narg() 
End Class 
Public Class A 
    Shared Sub New() 
     System.Console.WriteLine("Init A") 
    End Sub 
    Public Sub New() 
     System.Console.WriteLine("A Constructor") 
    End Sub 
End Class 

순서가 지정되지 않은 것입니다. 원래 코드와 동일한 순서가 허용되지만, C은 더 일찍 초기화 될 수 있습니다. 사실, 내 시스템의 출력은 다음과 같습니다

Init A 
A Constructor 
Init C 
Main 

이유는 C 지금 beforefieldinit 표시되어 있다는 점이다.


무료 채취 : 아니오, 귀하의 원래 코드는 그 출력을 보장하지 않습니다. 릴리스 빌드에서는 System.Diagnostics.Debug이 조건부로 호출되므로 출력이 없습니다.

+0

나는이 출력이 어떻게 합법적인지 이해하지 못한다 :'A'의 인스턴스는'Init' 출력이 나오기 바로 전에'New'를 통해 생성됩니다. 옵티 마이저 순서 재 지정 지침이 있습니까? 여기 왜 허락을 받았 니? 이것은 초기화 순서 (!)와는 아무런 관련이 없습니다. 부작용이있는 두 개의 인접한 명령문이 있습니다. –

+0

@Konrad :'beforefieldinit'는'C.A'가 사용되기 전에 언제든지'C' 이니셜 라이저가 실행되도록 허용합니다. 그래서이 경우 실제로'Main' 이전에 실행됩니다. 'Init A - A Constructor - Init C' 명령은 변경되지 않았습니다. 새로운 A는'A Constructor'를 호출하는'Narg()'에 생성됩니다. 그러나'A Constructor'는'A'에 대한 초기화 프로그램이 실행될 때까지 실행할 수 없으므로 JIT가 먼저 실행합니다. 'A Constructor'가 반환 된 후,'Narg()'가 계속 실행되고'Init C'를 출력합니다. 이것은 언급 된 하위 시퀀스를 발생시킵니다. –

+0

지금까지 너무 좋아. 하지만'A' *의 생성자는 Console 출력 "Init C"보다 먼저 초기화 프로그램 내부에서 호출되기 때문에'Main' 전에 실행해야합니다. –

5

예, 정적 및 인스턴스 생성자를 호출하는 순서는 언어 사양의 일부입니다. 모든 준수 컴파일러는이 프로그램에 대해 동일한 일리노이를 방출해야합니다.

+1

동시에 "같은 IL "beforefieldinit가 사용될 때 특히 형식 이니셜 라이저가 언제 실행되는지에 관해서 약간의 여유를두고 런타임을 떠납니다. –

관련 문제