2011-01-14 12 views
5

Il seguente frammento mi fornisce un elenco di costruttori e metodi di un tipo.Perché il costruttore predefinito non viene visualizzato per i tipi di valore?

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

Ma quando mi passa un tipo ‘int’ a questo metodo, perché non vedo il costruttore implicita nella produzione? Oppure, come modifico il codice precedente per elencare anche il costruttore predefinito (nel caso in cui mi manchi qualcosa nel mio codice).

+2

lettura interessante potrebbe essere: http://msmvps.com/blogs/jon_skeet/archive/2008/12/10/value-types- e-parameterless-constructors.aspx –

risposta

9

In C# (e nella maggior parte dei linguaggi CLI) - la specifica di un costruttore senza parametri su una struttura è proibita e, come tale, una struttura creata in C# (e nella maggior parte degli altri linguaggi .NET) non avrà nemmeno un costruttore parametrico definito nel I L. Il CLR inizializza sempre i tipi di valore utilizzando regole definite (in pratica, riempiendo tutti i valori con equivalenti pari a zero) e C# lo impone come unica opzione.

Poiché il costruttore predefinito senza parametri non esiste in una struttura generata in C#, non viene visualizzato quando si utilizza la riflessione.

+0

Reed, hai MSDN documentazione o un articolo su questo, quindi posso saperne di più? – Arun

+0

@Arun: http://msdn.microsoft.com/en-us/library/aa288208(VS.71).aspx "Le strutture non possono contenere costruttori senza parametri espliciti.I membri di Struct vengono automaticamente inizializzati con i loro valori predefiniti." –

+0

@Arun: Current - http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx - "Ogni tipo di valore ha un costruttore implicito predefinito che inizializza il valore predefinito di quel tipo." –

1

Questa è una differenza tra le specifiche C# e CLI. C# dice che tutti i tipi di valore hanno un costruttore parametrico predefinito (non sostituibile), ma questo non è il caso della CLI.

In molti casi, il tempo di esecuzione non esegue il costruttore predefinito anche se esiste (ciò è ragionevole poiché la maggior parte delle lingue che hanno come destinazione CIL non consentono di scriverne una); non fare nulla dopo aver riempito la struttura con zero. Ecco uno interesting article di Jon Skeet che fa esperimenti con l'hacking di un costruttore senza parametri in una struttura - a volte viene eseguito, ea volte no, a seconda del contesto.

In ogni caso, il motivo per cui l'API di reflection non mostra un tale costruttore senza parametri su quel tipo è perché non ce n'è uno.

1

Se volete qualsiasi costruttore di andare con lei può ottenere l'elenco delle Case costruttrici da

var consturctorList = type.GetContructors(); 

Se il valore del tipo di una struttura senza costruttori definiti in modo esplicito, si otterrà una lista vuota sopra dal costruttore implicito è non è disponibile per incasinare con esso nella riflessione, è possibile utilizzare il metodo di deserializzazione

FormatterServices.GetUninitializedObject(Type type) 
Problemi correlati