it-swarm.com.de

Private Variable gegen Eigentum?

Wenn Sie einen Wert für eine Variable innerhalb einer Klasse festlegen, stehen Ihnen meistens zwei Optionen zur Verfügung:

private string myValue;
public string MyValue
{
   get { return myValue; }
   set { myValue = value; }
}

Gibt es eine Konvention, die festlegt, wie wir Variablen innerhalb unserer Klassen Werte zuweisen sollen? Wenn ich beispielsweise eine Methode in derselben Klasse habe, sollte ich sie mithilfe der Eigenschaft oder der privaten Variablen zuweisen. Ich habe es in beide Richtungen gesehen, also habe ich mich gefragt, ob dies eine Wahl ist oder ob die Leistung ein Faktor ist (wahrscheinlich geringfügig).

42
Edward

Ich würde noch einen Schritt weiter gehen und es auf drei Fälle bringen. Obwohl es jeweils Variationen gibt, sind dies die Regeln, die ich die meiste Zeit bei der C # -Programmierung verwende.

Gehen Sie in den Fällen 2 und 3 immer zum Property Accessor (nicht zur Feldvariablen). Und in Fall 1 müssen Sie nicht einmal diese Wahl treffen.

1.) Unveränderliches Eigentum (an den Konstrukteur übergeben oder zur Bauzeit erstellt). In diesem Fall verwende ich eine Feldvariable mit einer schreibgeschützten Eigenschaft. Ich wähle dies einem privaten Setter vor, da ein privater Setter keine Unveränderlichkeit garantiert.

public class Abc
{ 
  private readonly int foo;

  public Abc(int fooToUse){
    foo = fooToUse;
  }

  public int Foo { get{ return foo; } }
}

2.) POCO-Variable. Eine einfache Variable, die in jedem öffentlichen/privaten Bereich abgerufen/festgelegt werden kann. In diesem Fall würde ich nur eine automatische Eigenschaft verwenden.

public class Abc
{ 
  public int Foo {get; set;}
}

3.) ViewModel-Bindungseigenschaften. Für Klassen, die INotifyPropertyChanged unterstützen, benötigen Sie meiner Meinung nach eine private Hintergrundvariable.

public class Abc : INotifyPropertyChanged
{
  private int foo;

  public int Foo
  {
    get { return foo; }
    set { foo = value;  OnPropertyChanged("foo"); }
  }
}
24

Im Allgemeinen würde ich sagen, dem Feld im Konstruktor zuweisen und die Eigenschaft überall anders verwenden. Auf diese Weise werden Sie nichts verpassen, wenn jemand der Eigenschaft Funktionen hinzufügt.

Es ist sicherlich kein Leistungsfaktor. Der Optimierer wird ein einfaches Abrufen oder Festlegen für Sie einbinden und der endgültige MSIL-Code wird wahrscheinlich identisch sein.

18
pdr

Hängt davon ab.

Zunächst sollten Sie nach Möglichkeit automatische Eigenschaften bevorzugen:

public string MyValue {get;set;}

Zweitens wäre der bessere Ansatz wahrscheinlich, die Eigenschaften zu verwenden. Wenn Sie dort eine Logik haben, sollten Sie diese wahrscheinlich selbst durchlaufen, insbesondere wenn diese Logik die Thread-Synchronisation ist.

Sie sollten jedoch auch berücksichtigen, dass dies Ihre Leistung beeinträchtigen kann (ein wenig). Wenn Sie falsch synchronisieren, können Sie sich selbst blockieren, und manchmal besteht der richtige Weg darin, die Logik in der Eigenschaft zu umgehen.

4
AK_

Nun, der direkte Ansatz wäre, es einfach der Variablen selbst zuzuweisen, da Sie sich in einer Klassenmethode befinden und das Verhalten der Klasse sowieso steuern.

Der springende Punkt bei Eigenschaften ist jedoch, dass sie die Variable weg abstrahieren. Während eine so einfache Eigenschaft wie in Ihrem Beispiel für eine einfache öffentliche Membervariable völlig nutzlos ist, tun (oder sollten) Eigenschaften normalerweise zusätzliche Dinge in ihren Gettern und Setzern. Und wenn Sie möchten, dass diese Dinge automatisch ausgeführt werden, wenn Sie die Eigenschaft innerhalb der Klasse ändern, ist es natürlich sauberer, an der Eigenschaft anstelle der Variablen zu arbeiten, damit nicht jede Variablenzuweisung geändert werden muss, wenn sich das Verhalten der Eigenschafteneinstellung ändert.

Sie müssen nur konzeptionell darüber nachdenken. Die Eigenschaft ist eigentlich ein Handle für den Zugriff auf einen internen Status des Objekts, der aus mehr als einer Mitgliedsvariablen bestehen kann. Sie müssen sich also fragen, ob Sie nur den zugrunde liegenden internen Zustand (oder nur einen Teil davon) oder die abstrakte Eigenschaft ändern möchten, die diesen Zustand insgesamt darstellt, und meistens ist es tatsächlich die letztere, da Sie normalerweise möchten, dass Ihr Objekt immer vorhanden ist ein konsistenter Zustand.

Wenn die Möglichkeit besteht, dass sich die Implementierung dieser Eigenschaft get/set manchmal später ändert (z. B. möchten Sie beim Aufrufen von set ein Ereignis auslösen, oder Sie fügen Ihrem get function), dann kann es eine gute Idee sein, dass Ihr Code innerhalb der Klasse die Eigenschaft in fast allen Fällen verwendet, außer in den - höchstwahrscheinlich seltenen - Fällen, in denen Sie diese explizit nicht wollen zu verwendende Ereignis- oder Lazy-Bewertungsmechanismen.

Was auch immer Sie tun werden, es besteht eine gute Chance, dass Sie, wenn Sie die Eigenschaftsimplementierung später so ändern, alle Stellen in Ihrer Klasse überprüfen müssen, die auf diese Eigenschaft zugreifen, um zu überprüfen, ob wirklich auf die Eigenschaft zugegriffen werden soll oder auf die private Variable verwendet werden.

2
Doc Brown

Ich benutze immer das öffentliche Eigentum.

Oft wird der set -Methode einer Eigenschaft eine Logik hinzugefügt, die immer ausgeführt werden sollte, wenn die Eigenschaft festgelegt wird. Wenn Sie stattdessen das private Feld festlegen, umgeht der öffentliche Setter die dortige Logik.

Sie haben einen Kommentar zu MVVM, der zu dieser Frage führt, und ich halte dies für noch wichtiger, wenn Sie mit MVVM arbeiten. Viele Objekte lösen eine PropertyChange Benachrichtigung des Setters aus, und andere Objekte können dieses Ereignis abonnieren, um eine Aktion auszuführen, wenn sich bestimmte Eigenschaften ändern. Wenn Sie die private Variable festlegen, werden diese Aktionen nur ausgeführt, wenn Sie das Ereignis PropertyChanged auch manuell auslösen.

2
Rachel

Im Allgemeinen liegt es an Ihnen, was Sie mit einer Eigenschaft und ihrem Hintergrundfeld beim Abrufen/Festlegen tun sollten.

Um im gesamten Code konsistent zu sein, sollten Sie meistens öffentliche Zugriffsmethoden verwenden, wo immer sie verfügbar und angemessen sind. Auf diese Weise können Sie mit minimaler Codeänderung eine Umgestaltung vornehmen. Wenn die Methode, die diese Einstellung vornimmt, aus der Klasse entfernt und an einer anderen Stelle abgelegt werden muss, an der das Hintergrundfeld nicht mehr verfügbar ist (wie bei einer Basisklasse), wen interessiert das? Sie verwenden etwas, das überall dort verfügbar ist, wo die Klasse selbst die Arbeit erledigen soll. Das Hintergrundfeld ist in den meisten Fällen ein Implementierungsdetail. Niemand außerhalb Ihrer Klasse sollte wissen, dass es existiert.

Die Hauptsituation, die ich mir vorstellen kann, wenn Sie das Hintergrundfeld und NICHT den Eigenschafts-Accessor verwenden sollten, ist, wenn der Accessor über zusätzliche Logik (Validierung oder Aktualisierung anderer Statusinformationen in der Klasse) verfügt, die Sie nicht ausführen möchten. Die anfängliche Grundgesamtheit eines Objekts ist ein Beispiel. Möglicherweise haben Sie eine Klasse, die zwei Eigenschaftswerte verwendet, um einen dritten zu berechnen, der ebenfalls in einem Hintergrundfeld gespeichert ist (aus Persistenzgründen). Beim Initialisieren einer neuen Kopie dieses Objekts mit Daten aus der Datenbank können sich die Eigenschaftszugriffsberechtigten, die jeweils den dritten Wert neu berechnen, beschweren, wenn der andere erforderliche Wert nicht festgelegt ist. Durch Verwenden der Hintergrundfelder zum Festlegen der Anfangswerte dieser zwei (oder drei) Eigenschaften umgehen Sie die Validierungs-/Berechnungslogik, bis sich die Instanz in einem konsistenten Zustand befindet, damit die Logik normal funktioniert.

1
KeithS

Verwenden Sie immer die, die Sinn macht. Ja, ich weiß, das klingt ziemlich falsch, bis es keine Antwort mehr gibt.

Der Zweck der Eigenschaften besteht darin, eine Schnittstelle bereitzustellen, über die Sie sicher auf ein Datenmodell zugreifen können. In den meisten Situationen möchten Sie immer sicher über diese Schnittstelle auf das Datenmodell zugreifen, z.

public Foo Bar
{
  get { return _bar; }
  set { _bar = doSomethingTo(value); }
}

In anderen Situationen verwenden Sie möglicherweise einfach eine Eigenschaft als Ansicht eines Datenmodells:

public Double SomeAngleDegrees
{
  get { return SomeAngleRadians * 180 / PI; }
  set { SomeAngleRadians = value * PI / 180; }
}

Wenn es sinnvoll ist, die Bogenmaßform von SomeAngle zu verwenden, verwenden Sie sie auf jeden Fall.

Trinken Sie am Ende unbedingt Ihre eigene Kool-Hilfe. Ihre öffentlich zugängliche API sollte stabil genug sein, um intern arbeiten zu können.

0
zzzzBov