Wie kann ich auf die Hintergrundvariable einer automatisch implementierten Eigenschaft zugreifen?

79

In der Vergangenheit haben wir Eigenschaften wie folgt deklariert:

public class MyClass
{
    private int _age;

    public int Age
    {
          get{ return _age;  }
          set{ _age = value; }
    }
}

Jetzt können wir tun:

public class MyClass
{
    public int Age {get; set;} 
}

Meine Frage ist, wie kann ich auf die private Variable zugreifen, die automatisch mit dieser Notation erstellt wird?

Ich würde lieber auf die private Variable zugreifen und nicht auf den öffentlichen Accessor 'Age'. Gibt es eine Standardnotation für den Zugriff auf die private Variable oder ist dies einfach nicht möglich?

öffentliche statische
quelle
10
Was ist in diesem Fall der Unterschied zwischen dem Zugriff auf den privaten und dem öffentlichen Zugriff? Ich denke, es ist eine bewährte Methode, auf den öffentlichen Zugriff zuzugreifen, selbst über die Logik in der deklarierenden Klasse. Wenn Sie dem Accessor jemals eine Logik hinzufügen, möchten Sie nicht Ihren gesamten Code ändern müssen.
Eric Schoonover
@ spoon16 Können Sie mir ein Beispiel geben, wie Sie dem Accessor Logik hinzufügen und als Ergebnis Ihren gesamten Code ändern müssen? Ich habe diesen Teil nicht wirklich verstanden.
Ogen

Antworten:

92

Das Ziel der neuen automatischen Eigenschaften ist es, die Menge an Boilerplate-Code zu reduzieren, die Sie schreiben müssen, wenn Sie nur eine einfache Eigenschaft haben, die keine spezielle Logik in get oder set benötigt.

Wenn Sie auf das private Mitglied zugreifen möchten, das diese Eigenschaften verwenden, hat dies normalerweise einige Gründe:

  • Sie müssen mehr als nur ein einfaches Abrufen / Festlegen durchführen. In diesem Fall sollten Sie die Verwendung automatischer Eigenschaften für dieses Mitglied vermeiden.
  • Sie möchten den Performance-Hit vermeiden, wenn Sie das Get oder Set durchlaufen, und das Mitglied direkt verwenden. In diesem Fall wäre ich überrascht, wenn es wirklich einen Performance-Hit gäbe. Die einfachen get / set-Mitglieder sind sehr, sehr einfach zu inline, und in meinen (zugegebenermaßen eingeschränkten) Tests habe ich keinen Unterschied zwischen der Verwendung der automatischen Eigenschaften und dem direkten Zugriff auf das Mitglied festgestellt.
  • Sie möchten nur öffentlichen Lesezugriff (dh nur ein 'get') und die Klasse schreibt direkt in das Mitglied. In diesem Fall können Sie einen privaten Satz in Ihrer automatischen Eigenschaft verwenden. dh

    public class MyClass
    {
        public int Age {get; private set;} 
    }

Dies deckt normalerweise die meisten Gründe ab, warum Sie direkt zu dem von den automatischen Eigenschaften verwendeten Hintergrundfeld gelangen möchten.

Wilka
quelle
Richtig - sie reduzieren den Bowlerplate-Code und ich werde auch darauf hinweisen, dass sie das reduzieren, was Sie zum Testen benötigen. Einige argumentieren möglicherweise, dass Sie das manuelle Abrufen / Festlegen testen müssen, jedoch nicht mit automatischen Eigenschaften, da Sie dem Framework vertrauen können.
Daniel Auger
3
Das Codebeispiel ist hier falsch. Es sollte die öffentliche Klasse MyClass {public int Age {get; private set;}} Ich stimme dieser Antwort zu. Sie können nicht auf das private Feld zugreifen, und wenn dies erforderlich ist, sollten Sie die automatischen Eigenschaften überhaupt nicht verwenden.
Hwiechers
hwiechers, danke dafür - ich hatte diese Bearbeitung, aber als ich versuchte, die Formatierung zu korrigieren, musste ich erneut auf Einfügen klicken und den falschen Codeblock löschen. Doh!
Wilka
Wird
23

Ihre Verwendung automatischer Eigenschaften impliziert, dass Sie keine Abruf- / Einstellungslogik für die Eigenschaft benötigen, sodass eine private Sicherungsvariable nicht erforderlich ist.

Verwenden Sie keine automatischen Eigenschaften, wenn Ihre Klasse eine komplexe Logik enthält. Gehen Sie einfach private int _ageund normale Getter / Setter, wie Sie es normalerweise tun würden.

IMO, automatische Eigenschaften eignen sich besser für die schnelle Implementierung von Wegwerfobjekten oder temporären Datenkapseln wie:

public class TempMessage {
    public int FromID { get; set; }
    public int ToID { get; set; }
    public string Message { get; set; }
}

Wo Sie nicht viel Logik brauchen.

Chakrit
quelle
Warum wirkt sich das Hinzufügen komplexer Logik zu Ihrer Klasse darauf aus, ob Sie automatische Eigenschaften innerhalb dieser Klasse verwendet haben oder nicht?
Eric Schoonover
Eher eine Konsistenzsache ... Wenn Sie eine komplexe Logik haben, möchten Sie über die private Sicherungsvariable gemäß den OO-Praktiken darauf zugreifen. Wenn Sie automatische Eigenschaften verwenden, dann ... gibt es Inkonsistenzen beim Zugriff auf diese Eigenschaften . da einige ein Unterstrichpräfix haben und andere nicht.
Chakrit
12

Diese Syntax wird allgemein als "Syntaxzucker" bezeichnet, was bedeutet, dass der Compiler diese Syntax verwendet und in etwas anderes übersetzt. In Ihrem Beispiel würde der Compiler Code generieren, der ungefähr so ​​aussieht:

[CompilerGenerated]
private int <Age>k_BackingField;

public int Age
{
   [CompilerGenerated]
   get
   {
      return this.<Age>k_BackingField;
   }
   [CompilerGenerated]
   set
   {
      this.<Age>k_BackingField = value;
   }

Selbst wenn Sie all das wissen, könnten Sie wahrscheinlich direkt auf das Hintergrundfeld zugreifen, aber diese Art von macht den Zweck der Verwendung automatischer Eigenschaften zunichte. Ich sage hier wahrscheinlich, weil Sie dann auf ein Implementierungsdetail angewiesen sind, das sich zu einem beliebigen Zeitpunkt in einer zukünftigen Version des C # -Compilers ändern könnte.

Scott Dorman
quelle
10

Hinter den Kulissen wird eine private Mitgliedsvariable mit dem Präfix <> k__AutomaticallyGeneratedPropertyField # eingefügt

Ab C # 3.0 Automatische Eigenschaften erklärt

Obwohl es möglich sein kann, dieses private Mitglied direkt zu verwenden, ist es sehr hackig und unnötig.

Macbirdie
quelle
7

Sie sollten nicht, und es ist sehr unwahrscheinlich, dass Sie müssen. Wenn Sie auf die Eigenschaft zugreifen müssen, verwenden Sie einfach die öffentliche Eigenschaft (z. B. this.Age). Das private Feld, das das öffentliche Eigentum unterstützt, hat nichts Besonderes. Es ist nur Aberglaube, es dem Eigentum vorzuziehen.

Keil
quelle
1
Ich habe mich immer gefragt, wozu automatische Eigenschaften gut sind. Wenn Sie keine spezielle Logik in Ihren Gettern und Setzern haben, warum haben Sie sie überhaupt?
Matthew Lock
4
@ MatthewLock Flexibilität. Mit direktem Feldzugriff sind Sie an dieses Design gebunden, es sei denn, Sie ändern den gesamten Clientcode gleichzeitig. Wenn Sie sich jedoch für eine Eigenschaft entscheiden, sie von einem "Pseudofeld" in eine berechnete Eigenschaft zu ändern, oder wenn Sie entscheiden, Zusicherungen und Überprüfungen für den Setter oder das, was Sie haben, hinzuzufügen, können Sie dies transparent tun. Dies ist noch nützlicher, wenn Sie Bibliothekscode schreiben, bei dem Sie nicht den gesamten Clientcode steuern können.
Wedge
2

Sie können nicht, es ist eine Sprachfunktion im Gegensatz zu einer IDE-Funktion. Um ehrlich zu sein, würde ich es vorziehen, wenn IDE die private Variable für Sie hinzufügt. Ich stimme zu, dass es etwas seltsam ist, wenn die Klasse intern den öffentlichen Einstiegspunkt verwenden muss, um auf ihre eigenen Variablen zuzugreifen. Daher benutze ich diese neue Funktion selbst nicht so oft.

Streit
quelle