5 Stimmen

Warum wird der Standardkonstruktor für Werttypen nicht angezeigt?

Der folgende Ausschnitt zeigt mir eine Liste der Konstruktoren und Methoden eines Typs.

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

Aber wenn ich dieser Methode einen Typ "int" übergebe, warum sehe ich dann den impliziten Konstruktor nicht in der Ausgabe? Oder wie ändere ich den obigen Code, um auch den Standardkonstruktor aufzulisten (falls ich etwas in meinem Code übersehe).

2 Stimmen

Interessante Lektüre vielleicht: msmvps.com/blogs/jon_skeet/archive/2008/12/10/

10voto

Reed Copsey Punkte 536986

In C# (und den meisten CLI-Sprachen) ist es verboten, einen parameterlosen Konstruktor für eine Struktur anzugeben. Daher wird für eine in C# (und den meisten anderen .NET-Sprachen) erstellte Struktur nicht einmal ein parameterloser Konstruktor in der AWL definiert. Die CLR initialisiert Werttypen immer mit definierten Regeln (im Grunde, füllen alle Werte mit Null-Äquivalente), und C # erzwingt, dass als die einzige Option.

Da der standardmäßige, parameterlose Konstruktor in einer von C# generierten Struktur nicht existiert, wird er bei Verwendung von Reflection nicht angezeigt.

0 Stimmen

Reed, haben Sie eine MSDN-Dokumentation oder einen Artikel zu diesem Thema, damit ich mehr erfahren kann?

0 Stimmen

@Arun: msdn.microsoft.com/de-us/library/aa288208(VS.71).aspx "Strukturen können keine expliziten parameterlosen Konstruktoren enthalten. Strukturmitglieder werden automatisch mit ihren Standardwerten initialisiert."

0 Stimmen

@Arun: Aktuell - msdn.microsoft.com/de-us/library/s1ax56ch.aspx - "Jeder Wertetyp hat einen impliziten Standardkonstruktor, der den Standardwert dieses Typs initialisiert."

1voto

Ani Punkte 107342

Dies ist ein Unterschied zwischen den C#- und CLI-Spezifikationen. C# besagt, dass alle Wertetypen einen (nicht überschreibbaren) parameterlosen Standardkonstruktor haben, aber das ist in der CLI nicht der Fall.

In vielen Fällen wird die Laufzeit no den Standardkonstruktor ausführen, selbst wenn er existiert (dies ist sinnvoll, da die meisten Sprachen, die auf CIL abzielen, es nicht zulassen, einen zu schreiben); nichts tun, nachdem die Struktur mit Nullen gefüllt wurde. Hier ist ein interessanter Artikel von Jon Skeet, der damit experimentiert, einen parameterlosen Konstruktor in eine Struktur zu hacken - manchmal funktioniert es, manchmal nicht, je nach Kontext.

In jedem Fall zeigt die Reflection-API einen solchen parameterlosen Konstruktor für diesen Typ nicht an, weil es ihn nicht gibt.

1voto

boskicthebrain Punkte 535

Wenn Sie einen beliebigen Konstruktor verwenden möchten, können Sie die Liste der Konstruktoren mit

var consturctorList = type.GetContructors();

Wenn Ihr Wert eine Struktur ohne explizit definierte Konstruktoren ist, erhalten Sie eine leere Liste oben, da der implizite Konstruktor nicht verfügbar ist, um in der Reflexion damit umzugehen, können Sie die Deserialisierungsmethode verwenden

FormatterServices.GetUninitializedObject(Type type)

-1voto

andreyk2 Hohlov Punkte 429

Warum wird der Standardkonstruktor für Werttypen nicht angezeigt?

Kurz gesagt, weil der Konstruktor für Werttypen NICHT EXISTIERT.

Ausführlichere Erklärung aquí :

Meines Wissens gibt es keinen Standardkonstruktor, der von der CLR definiert wurde, die Standardkonstruktor für Referenztypen wird vom C#-Compiler generiert selbst (oder anderen Sprachcompilern) erzeugt. CLR hat also keinen Standard Konstruktor für weder Referenz- noch Werttypen.

Für Referenztypen definiert C# einen standardmäßigen parameterlosen ctor , der auf den ctor der Basisklasse zurückgreift. Aber das ist die Aufgabe des C#-Compilers, diesen diesen Standard-Ctor-Code zu erzeugen, keine CLR. Jetzt für valuetype dies nicht geschehen (d.h. kein Standard-Ctor wird vom Compiler ausgegeben)

Da "int" ein Valye-Typ ist, gibt es keinen Konstruktor für ihn.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X