Feldinitialisierer Zugriff auf 'this' reloaded

8

Diese Frage ist eine Erweiterung von Cristi Diaconescu über die Rechtswidrigkeit von Feldinitialisierern, die auf this in C # zugreifen.

Dies ist in C # illegal:

%Vor%

Ok, also ist die vernünftige Erklärung dafür, warum dies illegal ist, unter anderem von Eric Lippert :

  

Kurz gesagt, die Möglichkeit, auf den Empfänger zuzugreifen, bevor der Konstruktorkörper ausgeführt wird, ist eine Eigenschaft von marginalen Vorteilen, die es einfacher macht, fehlerhafte Programme zu schreiben. Die C # -Sprachdesigner haben es daher vollständig deaktiviert. Wenn Sie den Empfänger verwenden müssen, legen Sie diese Logik in den Konstruktor-Hauptteil.

Auch die C # -Spezifikationen sind ziemlich einfach (bis zu einem gewissen Punkt):

  

Ein Variableninitialisierer für ein Instanzfeld kann nicht auf die Instanz verweisen, die gerade erstellt wird. Daher ist es ein Kompilierzeitfehler, in einem Variableninitialisierer darauf zu verweisen, da es ein Kompilierungsfehler für einen Variableninitialisierer ist, auf ein Instanzelement über einen einfachen Namen .

Meine Frage ist also: Was bedeutet " durch einen einfachen Namen "?

Gibt es einen alternativen Mechanismus, wo dies legal wäre? Ich bin mir sicher, dass fast jedes Wort in der Spezifikation aus einem ganz bestimmten Grund da ist. Was ist also der Grund, die Illegalität dieses speziellen Codes auf Referenzen durch einfache Namen zu beschränken?

BEARBEITEN Ich habe meine Frage nicht so gut formuliert. Ich frage nicht nach der Definition von " simple-name ", ich frage nach dem Grund für die Begrenzung der Illegalität auf dieses spezielle Szenario. Wenn es immer illegal ist, ein Instanzmitglied auf irgendeine Weise zu referenzieren, warum sollte es dann so eng angegeben werden? Und wenn nicht, welcher Mechanismus wäre dann legal?

    
InBetween 28.06.2013, 15:34
quelle

4 Antworten

5

Im allgemeinen Fall ist es nicht möglich, zu bestimmen, ob ein Ausdruck auf das zu konstruierende Objekt verweist, also zu verbieten und Compiler zu diagnostizieren, würde das Unmögliche erfordern. Bedenken Sie

%Vor%

Es ist möglich, und soweit ich weiß, auch wenn es eine schreckliche Idee ist, ein Objekt mit FormatterServices.GetUninitializedObject(typeof(A)) zu erstellen, setze A.Instance darauf und rufe dann den Konstruktor auf. Wenn b initialisiert wird, liest das Objekt sein eigenes a -Member.

%Vor%

Sie können Compiler-Fehler nur für das bekommen, was zur Kompilierzeit feststellbar ist.

    
hvd 28.06.2013, 17:11
quelle
1

Laut der Dokumentation :

  

Ein einfacher Name besteht aus einem einzelnen Bezeichner.

Ich nehme an, sie verdeutlichen dies, weil this.i in einer Klassenmethode i entspricht, wenn keine Variable namens i im Gültigkeitsbereich ist. Sie haben bereits die Verwendung von this außerhalb einer Instanzmethode verboten:

%Vor%

Wenn diese Sprache nicht vorhanden wäre, könnten einige dies so lesen, dass Sie auf Instanzvariablen verweisen können, indem Sie einfach das Schlüsselwort this weglassen.

Die beste Alternative ist die Verwendung eines Konstruktors:

%Vor%

Sie können das auch tun:

%Vor%

Dank der Tatsache, dass die zwei Mitglieder in verschiedenen Klassen sind, ist die Reihenfolge, in der sie initialisiert werden, eindeutig.

    
p.s.w.g 28.06.2013 15:44
quelle
1

Sie können immer etwas Durcheinander machen, wenn unmanaged Code ins Spiel kommt. Bedenken Sie Folgendes:

%Vor%

Ich habe ein bisschen Zeit damit verbracht, dies zu versuchen (für Kicks), habe aber nach einer Weile aufgegeben. Das heißt, Sie können einen Zeiger auf den Heap bekommen und dann einfach nach etwas suchen, das Sie als eine Instanz von A erkennen können und dann den Wert n daraus entnehmen. Es wäre schwer, aber es ist möglich.

    
Servy 28.06.2013 16:56
quelle
-1

Ich denke, Sie haben den letzten Satz nur falsch verstanden. Die Spezifikation gibt an, dass ein Instanzfeldinitialisierer nicht auf die erstellte Instanz verweisen kann. Es zitiert dann einfach Beispiele. Sie können this nicht verwenden und aus dem gleichen Grund können Sie keinen "einfachen Namen" verwenden, da ein einfacher Namezugriff implizit this verwendet. Die Spezifikation verengt die Fälle nicht. Es ruft einfach einige spezifische Konstruktionen auf, die illegal sind. Ein anderer würde base verwenden, um von einer Basisklasse auf ein geschütztes Feld zuzugreifen.

    
mike z 28.06.2013 18:23
quelle

Tags und Links