Warum ist es notwendig, zu nennen: die () auf einer Struktur verwenden automatische Eigenschaften in c #?

StackOverflow https://stackoverflow.com/questions/272153

Frage

Wenn ich definieren eine Struktur in C # mit automatischen Eigenschaften wie folgt aus:

public struct Address
{
    public Address(string line1, string line2, string city, string state, string zip)
    {
        Line1 = line1;
        Line2 = line2;
        City = city;
        State = state;
        Zip = zip;
    }

    public string Line1 { get; protected set; }
    public string Line2 { get; protected set; }
    public string City { get; protected set; }
    public string State { get; protected set; }
    public string Zip { get; protected set; }
}

Wenn ich die Datei erstellen versuchen, erhalte ich einen Kompilierungsfehler sagen The 'this' object cannot be used before all of its fields are assigned to. Dies kann durch Änderung der Konstruktor gelöst werden, um eine verkettete Aufruf der Standard-Konstruktor wie folgt vor:

public Address(string line1, string line2, string city, string state, string zip): this()
{
    Line1 = line1;
    Line2 = line2;
    City = city;
    State = state;
    Zip = zip;
}

Meine Frage ist, warum diese Arbeit, und was geschieht? Ich habe eine Vermutung, und ich versuchte, es zu beweisen, indem sie bei IL suchen, aber ich scherze mich nur, wenn ich glaube, ich IL brechen kann. Aber meine Vermutung ist, Auto-Eigenschaften arbeiten, indem die Compiler generieren Felder für Ihre Eigenschaften hinter den Kulissen. Diese Felder können nicht über Code zugegriffen werden, um alle Einstellungen und immer müssen über die Eigenschaften erfolgen. Wenn eine Struktur zu schaffen, kann ein Standard-Konstruktor nicht explizit definiert werden. So hinter den Kulissen muss der Compiler sein, ein Default-Konstruktor zu erzeugen, die die Werte der Felder festgelegt, die der Entwickler nicht sehen kann.

Jede und alle IL-Assistenten sind willkommen, um meine Theorie zu beweisen oder zu widerlegen.

War es hilfreich?

Lösung

Hinweis: wie von C # 6, ist dies nicht erforderlich - aber Sie sollten mit C # 6 sowieso ...

automatisch implementierter Eigenschaften nur gelesen werden, unter Verwendung von

this() stellt sicher, dass die Felder auf jeden Fall so weit wie der Compiler zugeordnet sind betroffen ist - es setzt alle Felder auf die Standardwerte. Sie verfügen über eine voll aufgebaut Struktur haben, bevor Sie den Zugriff kann beginnen jeder Eigenschaften.

Es ist ärgerlich, aber das ist so, wie es ist. Sind Sie sicher, dass Sie das wirklich eine Struktur obwohl sein? Und warum verwenden Sie einen geschützten Setter auf einer Struktur (die nicht abgeleitet werden)?

Andere Tipps

Eine Eigenschaft ist nichts anderes als eine Verkapselung eines Get Verfahren und / oder ein Set Verfahren. Die CLR hat Metadaten, die anzeigt, dass bestimmte Methoden sollten als eine Eigenschaften angesehen werden, Compiler Sinn sollten einige Konstrukte ermöglichen, die es nicht mit Methoden erlauben würde. Zum Beispiel, wenn X eine Schreib-Lese-Eigenschaft von Foo ist, wird ein Compiler Foo.X += 5 in Foo.SET_X_METHOD(Foo.GET_X_METHOD() + 5) übersetzen (obwohl die Methoden unterschiedlich benannt sind, und sind nicht allgemein zugänglich durch seinen Namen).

Obwohl ein autoproperty ein Paar get / set-Methoden implementiert, die ein privates Feld Zugriff auf eine solche Art und Weise, wie wie ein Feld mehr oder weniger verhalten, aus der Sicht von Code außerhalb des Eigentums ist ein autoproperty ein Paar von get / set-Methoden wie jede andere Eigenschaft. Folglich wird eine Aussage wie Foo.X = 5; als Foo.SET_X_METHOD(5) übersetzt. Da der C gerade # -Compiler, dass Anruf als Methode sieht, und da Methoden beinhalten keine Metadaten, um anzuzeigen, welche Felder sie lesen oder schreiben, wird der Compiler den Methodenaufruf verbieten, es sei denn es jedes Feld von Foo weiß geschrieben worden ist.

persönlich mein Rat wäre die Verwendung von autoproperties mit Strukturtypen zu vermeiden. Autoproperties sinnvoll mit Klassen, da es möglich ist, für Klasseneigenschaften Funktionen wie Update-Benachrichtigungen zu unterstützen. Auch wenn die frühen Versionen einer Klasse nicht Update-Benachrichtigungen unterstützen, diese Versionen eher eine autoproperty verwenden, die als ein Feld bedeutet, dass zukünftige Versionen Update-Benachrichtigungsfunktionen, ohne dass die Verbraucher der Klasse überarbeitet werden hinzufügen. Strukturen jedoch nicht sinnvoll die meisten der Arten von Funktionen unterstützen, die man sich wünschen könnte Feld ähnliche Eigenschaften hinzuzufügen.

Außerdem ist die Leistungsunterschiede zwischen den Feldern und Eigenschaften viel mehr mit großen Strukturen, als es mit Klassentypen ist. Tatsächlich viel von der Empfehlung große Strukturen zu vermeiden, ist eine Folge dieser Differenz. Große Strukturen können tatsächlich sehr effizient sein, wenn man sie unnötig Kopieren verhindert. Selbst wenn man eine enorme Struktur HexDecet<HexDecet<HexDecet<Integer>>> hat, wo HexDecet<T> ausgesetzt enthaltenen Felder F0..F15 vom Typ T, wäre eine Aussage wie Foo = MyThing.F3.F6.F9; einfach erfordert das Lesen eine ganze Zahl von MyThing und speichert es auf Foo, obwohl MyThing würde von riesiger von struct Standards ( 4096 ganze Zahlen belegen 16K). Darüber hinaus könnte man sehr leicht, dieses Element aktualisieren, z.B. MyThing.F3.F6.F9 += 26;. Wenn dagegen F0..F15 waren Auto-Eigenschaften würde die Anweisung Foo = MyThing.F3.F6.F9 Kopieren erfordern 1K von Daten von MyThing.F3 in einen temporären (nennen wir es temp1, dann 64 Bytes von Daten von temp1.F6 temp2), bevor sie schließlich um immer zu lesen 4 Bytes von Daten von temp2.F9. Ick. Schlimmer noch, 26 auf den Wert in MyThing.F3.F6.F9 hinzuzufügen versuchen, wäre so etwas wie var t1 = MyThing.F3; var t2 = t1.F6; t2.F9 += 26; t1.F6 = f2; MyThing.F3 = t1; erfordern.

Viele der langjährigen Beschwerden über „wandelbar Strukturtypen“ sind wirklich Beschwerden über Strukturtypen mit Lese- / Schreibeigenschaften. Ersetzen Sie einfach Eigenschaften mit Feldern und die Probleme verschwinden.

PS: Es gibt Zeiten, es sinnvoll sein kann, eine Struktur, die Eigenschaften zugreifen Objekt eine Klasse zu haben, zu dem sie einen Verweis halten. Zum Beispiel wäre es schön, eine Version einer ArraySegment<T> Klasse zu haben, die man Var foo[] = new int[100]; Var MyArrSeg = New ArraySegment<int>(foo, 25, 25); MyArrSeg[6] += 9; erlaubt zu sagen, und hat die letzte Anweisung neun Elemente hinzufügen (25 + 6) von foo. In älteren Versionen von einem C # könnte das tun. Leider ist die häufige Verwendung von autoproperties in dem Rahmen, in dem Feld besser geeignet, um weit verbreitete Beschwerden über den Compiler so dass p geführt worden wäre,roperty Setter namens unnütz auf Nur-Lese-Strukturen werden; folglich auf einer Nur-Lese-Struktur wird nun jede Eigenschaft Setter Aufruf verboten, ob die Eigenschaft Setter tatsächlich alle Felder der Struktur ändern würde. Wenn die Menschen einfach aus machen structs wandelbar über Eigentum Setter (Herstellung Felder direkt zugänglich ist, wenn Veränderlichkeit angemessen war) darauf verzichtet hatten Compiler hätte nie diese Einschränkung zu implementieren hat.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top