2011-01-14 3 views
5

아래 스 니펫은 유형의 생성자 및 메소드 목록을 제공합니다. 나는이 방법에 'INT'유형을 통과 할 때값 형식에 기본 생성자가 표시되지 않는 이유는 무엇입니까?

static void ReflectOnType(Type type) 
{ 
    Console.WriteLine(type.FullName); 
    Console.WriteLine("------------"); 
    List<ConstructorInfo> constructors = 
      type.GetConstructors(BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic |BindingFlags.Instance | BindingFlags.Default).ToList(); 

    List<MethodInfo> methods = type.GetMethods().ToList(); 

    Type baseType = type.BaseType; 

    while (baseType != null) 
    { 
      constructors.AddRange(baseType.GetConstructors(BindingFlags.Public | BindingFlags.Static | BindingFlags.NonPublic | 
           BindingFlags.Instance | BindingFlags.Default)); 
      methods.AddRange(baseType.GetMethods()); 
      baseType = baseType.BaseType; 
    } 

    Console.WriteLine("Reflection on {0} type", type.Name); 

    for (int i = 0; i < constructors.Count; i++) 
    { 
     Console.Write("Constructor: {0}.{1}", constructors[i].DeclaringType.Name, constructors[i].Name); 
     Console.Write("("); 
     ParameterInfo[] parameterInfos = constructors[i].GetParameters(); 
     if (parameterInfos.Length > 0) 
     { 
      for (int j = 0; j < parameterInfos.Length; j++) 
      { 
       if (j > 0) 
       { 
        Console.Write(", "); 
       } 
       Console.Write("{0} {1}", parameterInfos[j].ParameterType, parameterInfos[j].Name); 
      } 
     } 
     Console.Write(")"); 

     if (constructors[i].IsSpecialName) 
     { 
      Console.Write(" has 'SpecialName' attribute"); 
     } 
     Console.WriteLine(); 
    } 
    Console.WriteLine(); 

    for (int i = 0; i < methods.Count; i++) 
    { 
     Console.Write("Method: {0}.{1}", methods[i].DeclaringType.Name, methods[i].Name); 
     // Determine whether or not each field is a special name. 
     if (methods[i].IsSpecialName) 
     { 
      Console.Write(" has 'SpecialName' attribute"); 
     } 
     Console.WriteLine(); 
    } 
} 

는하지만, 내가 왜 출력에 암시 적 생성자를 표시되지 않는 이유는 무엇입니까? 또는, 위 코드를 수정하여 기본 생성자를 나열하는 방법 (코드에 뭔가 빠졌을 경우를 대비하여).

+2

재미있는 읽기가있을 수 있습니다 : http://msmvps.com/blogs/jon_skeet/archive/2008/12/10/value-types- and-parameterless-constructors.aspx –

답변

9

구조체에 매개 변수없는 생성자를 지정하는 것은 금지되어 있으므로 C# 및 기타 .NET 언어로 작성된 구조체에는 IL. CLR은 항상 정의 된 규칙 (기본적으로 모든 값을 0 등가로 채 웁니다)을 사용하여 값 유형을 초기화하며 C#은이를 유일한 옵션으로 시행합니다.

매개 변수가없는 기본 생성자는 C# 생성 구조체에 없으므로 리플렉션을 사용할 때 표시되지 않습니다.

+0

리드 (Reed), 모든 MSDN이 있습니다. 문서 또는 이에 대한 기사를 읽으면서 더 많은 것을 배울 수 있습니까? – Arun

+0

@Arun : http://msdn.microsoft.com/en-us/library/aa288208(VS.71).aspx "구조체는 명시적인 매개 변수없는 생성자를 포함 할 수 없습니다. 구조체 멤버는 자동으로 기본값으로 초기화됩니다." –

+0

@Arun : Current - http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx - "각 값 형식에는 해당 형식의 기본값을 초기화하는 암시 적 기본 생성자가 있습니다." –

1

이것은 C# 및 CLI 사양의 차이점입니다. C#에서는 모든 값 유형에 (무시할 수없는) 기본 매개 변수없는 생성자가 있지만 CLI에서는 그렇지 않습니다.

대부분의 경우 런타임은 이 아니며은 기본 생성자를 실행합니다 (CIL을 대상으로하는 대부분의 언어는 사용자가 작성할 수 없으므로 합리적입니다). 구조체를 0으로 채운 후에는 아무것도하지 않습니다. Jon Skeet의 interesting article은 구조체에 매개 변수없는 생성자를 해킹하는 실험을합니다. 상황에 따라 때때로 실행되고 때로는 실행되지 않습니다.

리플렉션 API가 해당 유형에 매개 변수없는 생성자가 표시되지 않는 이유는 그 이유가 없습니다. 당신이 당신의 값이 더 명시 적으로 정의 된 생성자와 구조체를 입력하면

var consturctorList = type.GetContructors(); 

에 의해 contructors의 목록을 얻을 수 있습니다 당신과 함께 가고있는 생성자를 원하는 경우 암시 적 생성자이기 때문에

1

, 당신은 위의 빈 목록을 얻을 것이다 사용할 수없는 반사에 함께 장난을 위해, 당신은 직렬화 방법을 사용할 수 있습니다

FormatterServices.GetUninitializedObject(Type type) 
관련 문제