Können Sie erkennen, ob einem C # -Feld ein Standardwert zugewiesen wurde?

7

Angenommen, Sie haben eine Klassendeklaration, z. B .:

%Vor%

Nun, gibt es einen Weg im generischen Code, der Reflektion (oder irgendein anderes Mittel dafür) verwendet, dass ich folgern kann, dass myInt einen Standardwert zugewiesen hat, während myOtherInt dies nicht tut? Beachten Sie den Unterschied zwischen der Initialisierung mit einem expliziten Standardwert und dem Verlassen des impliziten Standardwerts (myOtherInt wird standardmäßig auf 0 initialisiert).

Aus meiner eigenen Forschung sieht es so aus, als ob es keine Möglichkeit dafür gibt - aber ich dachte, ich würde hier fragen, bevor ich aufhöre.

[Bearbeiten]

Auch bei nullfähigen Typen und Referenztypen möchte ich zwischen denen, die als null belassen wurden, und denen, die explizit auf null initialisiert wurden, unterscheiden. Dies ist so, dass ich sagen kann, dass Felder mit einem Initialisierer "optional" sind und andere Felder "obligatorisch" sind. Im Moment muss ich das mit Attributen machen - was mich in diesem Fall mit ihrer Informationsredundanz kritisiert.

    
philsquared 07.11.2008, 12:20
quelle

13 Antworten

18

Ich habe Ihren Code kompiliert und in ILDASM geladen und habe diesen

bekommen %Vor%

Beachten Sie, dass die ldc.i4.7 und stfld int32 dummyCSharp.MyClass::myInt Anweisungen zum Festlegen der Standardwerte für das Feld myInt zu sein scheinen.

Eine solche Zuweisung wird also tatsächlich als zusätzliche Zuweisungsanweisung in einem Konstruktor kompiliert.

Um eine solche Zuweisung zu erkennen, benötigen Sie eine Reflexion, um die IL der MyClass-Konstruktormethode zu reflektieren und nach stfld (set fields?) - Befehlen zu suchen.

EDIT: Wenn ich dem Konstruktor explizit eine Zuweisung hinzufüge:

%Vor%

Wenn ich es in ILDASM lade, habe ich Folgendes:

%Vor%

Beachten Sie, dass die zusätzliche Zuweisung für myOtherInt, die ich hinzugefügt habe, hinzugefügt wurde, nachdem der Konstruktor der Object-Klasse aufgerufen wurde.

%Vor%

Also da hast du es,

Jede Zuweisung vor ist der Aufruf des Konstruktors der Object-Klasse in IL ist eine Standardwertzuweisung.

Alles, was darauf folgt, ist eine Anweisung innerhalb des tatsächlichen Konstruktorcodes der Klasse.

Es sollte jedoch ein umfangreicherer Test durchgeführt werden.

ps. das hat Spaß gemacht: -)

    
chakrit 07.11.2008, 12:32
quelle
4

Vielleicht möchten Sie für dieses Verhalten einen Nullwert int:

%Vor%     
duckworth 07.11.2008 12:25
quelle
3

Ein Standardwert ist ein Wert wie jeder andere. Es gibt keine Möglichkeit, zwischen diesen beiden Fällen zu unterscheiden:

%Vor%

In beiden Fällen geben Sie ihnen den Wert 0, eine Art rettet Sie nur beim Tippen. Es gibt keinen magischen "standardmäßigen nicht initialisierten Wert" - sie sind beide null. Sie funktionieren genau gleich. Aber die Tatsache, dass Sie darüber nachdenken, deutet darauf hin, dass Sie ernsthaft von guten Ideen abweichen. Was machst du? Was ist dein spezifisches Bedürfnis? Sie stellen die falsche Frage;)

    
Sander 07.11.2008 12:31
quelle
2

Folgendes würde ich tun, wenn ich dies als allgemeine Laufzeitfunktion erstellen möchte. Für Skalartypen würde ich ein Standardwertattribut erstellen und das zur Bestimmung der Standardität verwenden.

Hier ist eine Teillösung für die Aufgabe - ich bin mir sicher, dass es besser sein könnte, aber ich habe es einfach ausgeschaltet:

%Vor%     
plinth 07.11.2008 15:52
quelle
1

Für Werttypen, die einen nullfähigen Typ für optionale Parameter verwenden, sollte funktionieren. Zeichenfolgen können auch initialisiert werden, um sie zu leeren, wenn sie nicht optional sind.

%Vor%

Wie auch immer, das erscheint mir ein bisschen dreckig, ich würde bei den Attributen bleiben, um dies klar zu machen.

    
Jack Ryan 07.11.2008 12:43
quelle
1

Vielleicht ist das nicht die einfachste Lösung ...

Sie können das defaultValue-Attribut verwenden, um den Wert wie folgt zu setzen:

Importieren Sie System.ComponentModel und System.Reflection

%Vor%

Und dann den Standardwert mit Reflektion wiederherstellen:

%Vor%     
Javier Suero Santos 07.11.2008 13:37
quelle
1

Wie wäre es mit einer generischen Struktur, die einen Wert und ein initialisiertes Flag enthält?

%Vor%

Dann verwenden Sie dies anstelle der Mitglieder, die Sie über die Initialisierung von kennen müssen. Es ist eine ziemlich grundlegende Variation über eine faule Zukunft oder Versprechen.

    
Edward KMETT 07.11.2008 15:25
quelle
0

Dieser Ansatz verwendet den Eigenschaft-get / set-Prozess:

%Vor%

Das ist viel Code für ein Feld - Hallo Snippets!

    
Doug L. 07.11.2008 13:07
quelle
0

Sie können die Felder in private / protected-Eigenschaften umbrechen. Wenn Sie wissen möchten, ob es gesetzt wurde oder nicht, überprüfen Sie das private Feld (z. B. _myInt.HasValue ()).

%Vor%     
dviljoen 07.11.2008 15:10
quelle
0

Wenn du das willst, dann schau dir den Code unten an.
Es steht geschrieben in Oxygene [1], hoffe das ist kein Problem.

[1] oder Delphi Prism, wie es jetzt heißt

%Vor%

Ausgabe:

%Vor% %Vor%     
Robert Giesecke 07.11.2008 17:26
quelle
-1

Der Compiler kann so eingestellt werden, dass er eine Warnung generiert, wenn Sie versuchen, eine Variable zu verwenden, bevor Sie ihr einen Wert zuweisen. Ich habe die Standardeinstellung und das wie es sich verhält.

    
Hapkido 07.11.2008 12:31
quelle
-1

Huseyints Vorschlag funktioniert nicht, weil Sie die "Verwendung der nicht zugewiesenen lokalen Variablen 'sp_id'"

erhalten     
TheAkkadian 26.11.2008 17:20
quelle
-2

Hilft die folgende Hilfe:

%Vor%     
huseyint 07.11.2008 12:36
quelle

Tags und Links