2017-10-25 3 views
0

Sint 매개 변수로 선언되면 값 유형 로컬 변수 (예 : S s;struct S{})가 해당 생성자 (예 : a = new S(11))의 호출을 통해 초기화됩니다. s는 필드 (예컨대 class C { S s;) 인 경우는왜 값 유형 필드가 초기화되는 대신 초기화 될 수 있습니까?

ldloca.s V_0 
ldc.i4.s 11 
call  instance void S::.ctor(int32) 

그러나 다음 동일한 방식으로 초기화되지 : 다음은 new S(11)로 컴파일.

ldarg.0 
ldflda valuetype S C::s 
ldarg.1 
call  instance void S::.ctor(int32) 
: 나는 그것이 지역 변수의 경우에 더 가까운 다음 코드로 컴파일 할 것이라고 예상하고 있었다

ldarg.0 
ldarg.1 
newobj  instance void S::.ctor(int32) 
stfld  valuetype S C::s 

:에이 컴파일 void setS(int n) { s = new S(n); } : 클래스 C 다음 인스턴스 메소드에 대해서

또한 명확하게 이해하면 newobj instance void S::.ctor(int32)은 높은 오버 헤드와 부담을줍니다. 나 맞아?

왜 C# 컴파일러는 값 유형 필드에 로컬 변수에 사용 된 것과 다른 접근 방식을 사용합니까?

+1

Jon의 정답 메모와 같이 최적화 된 버전이 최적화되지 않은 버전과 다른 관찰 가능한 동작을 생성 할 수있는 경우 최적화를 수행 할 수 없습니다. 참고로이 최적화는 "복사본 추출"이라고하며 C++ 컴파일러에서 일반적으로 사용됩니다. 그것에 대해 더 자세히 알고 싶다면 이제 사용할 수있는 검색어를 알 수 있습니다. –

답변

4

기본적으로이 동작은 생성자 호출을 할당에서 분리하기 위해 필요합니다.

예상되는 관찰 가능한 동작은 생성자가 예외를 throw하면 할당이 수행되지 않는다는 것입니다. 생성자가 필드/스택 슬롯에 직접 쓰는 "최적화 된"버전에서는 그렇지 않습니다. 경우 지역 변수에 할당 할 때

동일한 IL을 볼 수

  • 변수가 이미 선언
  • 변수 전에 할당 예외가 발생하면 여전히 접근했다

동일한 질문은 아니지만 자세한 내용은 in this SO post이며 Eric Lippert's blog입니다.

관련 문제