2011-01-14 8 views
5

El siguiente fragmento me da una lista de constructores y métodos de un tipo.¿Por qué el constructor predeterminado no aparece para los tipos de valores?

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(); 
    } 
} 

Pero cuando paso un tipo ‘int’ a este método, ¿por qué no aparece el constructor implícito en la salida? O bien, ¿cómo modifico el código anterior para listar también el constructor predeterminado (en caso de que me falte algo en mi código)?

+2

interesante leer puede ser: http://msmvps.com/blogs/jon_skeet/archive/2008/12/10/value-types- and-parameterless-constructors.aspx –

Respuesta

9

En C# (y la mayoría de los lenguajes CLI), está prohibido especificar un constructor sin parámetros en una estructura, y como tal, una estructura creada en C# (y la mayoría de los lenguajes .NET) ni siquiera tendrá un constructor sin parámetros definido en ILLINOIS. El CLR siempre inicializa los tipos de valor utilizando reglas definidas (básicamente, completando todos los valores con cero equivalentes), y C# lo impone como la única opción.

Como el constructor sin parámetros predeterminado no existe en una estructura generada en C#, no se muestra cuando se utiliza la reflexión.

+0

Reed, tiene cualquier MSDN documentación o un artículo sobre esto para que pueda aprender más? – Arun

+0

@Arun: http://msdn.microsoft.com/en-us/library/aa288208(VS.71).aspx "Las estructuras no pueden contener constructores explícitos sin parámetros. Los miembros de Struct se inicializan automáticamente a sus valores predeterminados." –

+0

@Arun: Current - http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx - "Cada tipo de valor tiene un constructor predeterminado implícito que inicializa el valor predeterminado de ese tipo". –

1

Esta es una diferencia entre las especificaciones C# y CLI. C# dice que todos los tipos de valores tienen un constructor sin parámetros predeterminado (no reemplazable), pero este no es el caso con la CLI.

En muchos casos, el tiempo de ejecución se no ejecutar el constructor por defecto, incluso si existe (esto es razonable, ya que la mayoría de los idiomas que se dirigen a CIL no permiten escribir uno); no hacer nada después de llenar la estructura con ceros. Aquí hay un interesting article de Jon Skeet que experimenta con la piratería de un constructor sin parámetros en una estructura; a veces se ejecuta, y algunas veces no, según el contexto.

En cualquier caso, el motivo por el que la API de reflexión no muestra un constructor sin parámetros en ese tipo es porque no hay uno.

1

Si desea cualquier constructor para ir con usted puede obtener la lista de contructors por

var consturctorList = type.GetContructors(); 

Si el valor del tipo de una estructura sin constructores definidos explícitamente, obtendrá una lista vacía anteriormente, ya que el constructor implícito es no está disponible para jugar con él en la reflexión, se puede utilizar el método de deserialización

FormatterServices.GetUninitializedObject(Type type) 
Cuestiones relacionadas