2011-03-31 3 views
9

C# 4.0의 "optional parameters"기능이 매우 흥미로웠다. 그래서 어떻게 만들어 졌는지 알아 내려고 노력했다. 그래서 나는이 같은 방법을 썼다 : 다음,MSIL에서 [opt]는 무엇을 의미합니까?

private static void A(int a = 5) { } 

그것을 컴파일을 IL DASM 그것을 디 컴파일, 이는 IL 코드 :

.method private hidebysig static void A([opt] int32 a) cil managed 
{ 
    .param [1] = int32(0x00000005) 
    // Code size  2 (0x2) 
    .maxstack 8 
    IL_0000: nop 
    IL_0001: ret 
} // end of method Program::A 

그리고 메타 데이터에서이 문제를 가지고있다 :

(1) ParamToken : (08000002)의 이름 : 플래그 : [선택 사항] [HasDefault] (00001010) 기본값 : (I4)가 5

그래서 내가 단서를 다음과 같은 방법을 썼다 :

private static void B([Optional, DefaultParameterValue(78)]int b) { } 

컴파일하고 컴파일을 해본 결과, C# 컴파일러가 A와 B (이름 제외)와 거의 동일한 MSIL 코드를 생성한다는 것을 알게되었습니다.

우리는 거기에 IL 코드의 속성의 흔적이없고 잘못 생각, 그래서 이런 사용자 지정 특성 썼다 볼 수 있듯이 : 다음

[AttributeUsage(AttributeTargets.Parameter)] 
public class MyTestAttribute : Attribute 
{ 
} 

을이 같은 방법 C에서 그것을 사용 :

private static void C([MyTest]int c) { } 

그것을 컴파일 한 후 디 컴파일을하고, HAH,이 발견 :

.method private hidebysig static void C(int32 c) cil managed 
{ 
    .param [1] 
    .custom instance void ConsoleApplication1.MyTestAttribute::.ctor() = (01 00 00 00) 
    // Code size  2 (0x2) 
    .maxstack 8 
    IL_0000: nop 
    IL_0001: ret 
} // end of method Program::C 

의 두 번째 줄 메서드 본문 내 사용자 지정 속성의 ctor를 호출합니다.

그래서이 내 의심에 이르게 :

  1. [옵트] 무엇을 의미합니까? 나는 방법 A와 B의 매개 변수 앞에 나타나는 것을 의미합니다.
  2. 메서드 C가 해당 매개 변수에 적용되는 특성의 생성자를 어떻게 호출하고 A와 B 메서드는 그렇지 않습니까?
  3. 메타 데이터에서 DefaultParameterValueAttribute의 기호를 찾을 수없는 것 같지만 OptionalAttribute 및 MyTestAttribute를 찾을 수 있습니다. 왜 그런가요? 제가 누락 된 것이 있습니까?

미리 감사드립니다.

답변

10

Param 메타 데이터 테이블에서 이미 Flags 열을 통해 선택적 및 기본값을 설명 할 수 있으므로 C# 컴파일러에서 특성을 내보낼 필요가 없습니다. 23.1.13에서

ECMA 335에 : (|가 0x1000 0x0010)

Flag   Value Description 
----------------------------------------------------- 
In    0x0001 Parameter is [In] 
Out    0x0002 Parameter is [Out] 
Optional  0x0010 Parameter is optional 
HasDefault  0x1000 Parameter has a default value 
HasFieldMarshal 0x2000 Parameter has FieldMarshal 

매개 변수는 선택 사항이며 지정하고 디폴트 값을 갖는 플래그 값을 가질 수 있습니다. 기본값이있는 매개 변수는 상수 메타 데이터 테이블에 연결된 토큰을 갖습니다.

상수 메타 데이터 테이블에는 문제의 Param 토큰이 될 Parent 열과 기본값이 저장되는 blob 힙에 대한 인덱스가 될 Value 열이 있습니다.

그래서 귀하의 질문에 대답 :

  1. [옵트]은 옵션 플래그 세트가있는 파람 토큰에 대한 Flags 열을 의미한다.
  2. 위에서 언급했듯이 C# 컴파일러는 Optional/DefaultParameterValue 특성을 인식하고 단순히 매개 변수 플래그로 변환한다는 것입니다.
  3. 편집 : 매개 변수에 Optional 플래그가 사용 되어도 C# 컴파일러에서 OptionalAttribute에 대해 사용되지 않는 TypeRef가 방출되는 것 같습니다. DefaultParameterValueAttribute에 대한 TypeRef를 방출하지 않습니다. 사용되지 않는 TypeRefs/MemberRefs를 방출하는 작은 컴파일러 버그 일 수 있습니다.
+0

고마워, 나는 그렇게 빨리 답변을 기대하지 않았다. 하지만 당신 것 같아요. – CuiPengFei

+0

그리고 나는 opt가 최적화를 의미한다고 생각해 왔습니다 ... – CuiPengFei

+0

와우, CSC 버그를 찾으려고하지 않았습니다. – CuiPengFei

2

2/3; 컴파일러가 실제 메타 데이터가 아닌 IL 메타 데이터로 해석하는 몇 가지 속성이 있습니다. 이것이 여기에있는 것처럼 보입니다. [Serializable]이 또 다른 예입니다. 기본에 대한 데이터가 : Default: (I4) 5 - 코드가 아닌 모든 속성은 메타 데이터 (다시, 내가 여기 [Serializable] 찾고 있어요) [Serializable] (댓글) 그 시점을 다시


에 속성이 될;

[Description("abc")] 
class Foo { } 

[Serializable] 
class Bar { } 

하는 핵심 IL은 다음과 같습니다 : 여기 예입니다 Foo에서

.class private auto ansi beforefieldinit Foo 
    extends [mscorlib]System.Object 
{ 
    .custom instance void [System]System.ComponentModel.DescriptionAttribute::.ctor(string) = { string('abc') } 
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed 
    { 
    } 

} 
.class private auto ansi serializable beforefieldinit Bar 
    extends [mscorlib]System.Object 
{ 
    .method public hidebysig specialname rtspecialname instance void .ctor() cil managed 
    { 
    } 

} 

(일부 임의의 속성에 대해) 우리가 얻을 :

.custom instance void [System]System.ComponentModel.DescriptionAttribute::.ctor(string) = { string('abc') } 

그러나이 적용되지 않습니다 [Serializable]; 대신 그 유형의 일부입니다 :

.class private auto ansi serializable beforefieldinit Bar 
+1

고마워, 그게 많이 설명해. BTW, "선택 매개 변수"에 대해 검색 할 때 게시글을 보았습니다. – CuiPengFei

+0

실제로 테스트했는데 실제로 Serializable은 메타 데이터의 reftype 섹션에 나타납니다. – CuiPengFei

+0

@CuiPengFei - 설명하기 위해 업데이트 –