it-swarm.com.de

Best Practices für Getter, Setter und Eigenschaften. Java vs. C #

Ich nehme gerade einen C # -Kurs und versuche, die beste Vorgehensweise herauszufinden. Ich komme aus einem Java-Hintergrund und kenne daher nur Java-Best Practices. Ich bin ein C # -Anfänger!

Wenn ich in Java ein privates Eigentum habe, mache ich das;

private String name;

public void setName(String name) {
   this.name = name;
}

public String getName() {
   return this.name;
}

In C # sehe ich, dass es viele Möglichkeiten gibt, dies zu tun.

Ich kann es wie Java machen:

private string name;

public void setName(string name) {
   this.name = name;
}

public string getName() {
   return this.name;
}

Oder ich kann es so machen:

private string name;

public string Name {
   get { return name; }
   set { name = value; }
}

Oder:

public string Name { get; set; }

Welches sollte ich verwenden, und welche sind die Vorbehalte oder Feinheiten, die mit jedem Ansatz verbunden sind? Beim Erstellen von Klassen befolge ich allgemeine Best Practices, die ich von Java kenne (insbesondere Lesen von Effective Java). Ich befürworte beispielsweise die Unveränderlichkeit (Setter nur wenn nötig). Ich bin nur neugierig, wie diese Praktiken zu den verschiedenen Möglichkeiten passen, Setter und Getter in C # bereitzustellen. im Wesentlichen, wie würde ich Best Practices aus der Java-Welt in C # übersetzen?

EDIT

Ich habe dies als Kommentar zu Jon Skeets Antwort gepostet, aber dann wurde es lang:

Was ist mit einer nicht trivialen Eigenschaft (d. H. Möglicherweise mit erheblicher Verarbeitung und Validierung)? Könnte ich es trotzdem über eine öffentliche Eigenschaft freigeben, jedoch mit der in get und set gekapselten Logik? Warum sollte/sollte ich dies tun, weil ich dedizierte Setter- und Getter-Methoden (mit zugehöriger Verarbeitungs- und Validierungslogik) habe?.

87
Vivin Paliath

Pre-C # 6

Ich würde den letzten von ihnen für eine triviale Eigenschaft verwenden. Beachten Sie, dass ich dies eine public - Eigenschaft nennen würde, da sowohl die Getter als auch die Setter öffentlich sind.

Unveränderlichkeit ist mit automatisch implementierten Eigenschaften ein wenig schmerzhaft - Sie können keine Auto-Eigenschaft schreiben, die nur einen Getter hat. am nächsten können Sie kommen:

public string Foo { get; private set; }

was nicht wirklich unveränderlich ist ... nur unveränderlich außerhalb Ihrer Klasse. Möglicherweise möchten Sie stattdessen eine schreibgeschützte real - Eigenschaft verwenden:

private readonly string foo;
public string Foo { get { return foo; } }

Sie wollen definitiv nicht getName() und setName() schreiben. In einigen Fällen ist es sinnvoll, Get/Set-Methoden zu schreiben, anstatt Eigenschaften zu verwenden, insbesondere wenn sie teuer sein könnten und Sie dies hervorheben möchten. Sie möchten jedoch die .NET-Namenskonvention von PascalCase für Methoden einhalten, und Sie möchten nicht, dass eine triviale Eigenschaft wie diese mit normalen Methoden implementiert wird - eine Eigenschaft ist hier viel idiomatischer.

C # 6

Hooray, wir haben endlich die richtigen schreibgeschützten, automatisch implementierten Eigenschaften:

// This can only be assigned to within the constructor
public string Foo { get; }

Ebenso für schreibgeschützte Eigenschaften, für die do einige Arbeit verrichten muss, können Sie Elementeigenschaften verwenden, die sich auf Mitglieder beziehen:

public double Area => height * width;
83
Jon Skeet

Wenn Sie nur eine Variable benötigen, um Daten zu speichern:

public string Name { get; set; }

Möchten Sie es schreibgeschützt erscheinen lassen?

public string Name { get; private set; }

Oder noch besser ...

private readonly string _name;

...

public string Name { get { return _name; } }

Möchten Sie vor der Zuweisung der Eigenschaft eine Wertprüfung durchführen?

public string Name 
{
   get { return m_name; }
   set
   {
      if (value == null)
         throw new ArgumentNullException("value");

      m_name = value;
   }
}

In der Regel werden GetXyz () und SetXyz () nur in bestimmten Fällen verwendet, und Sie müssen nur Ihren Verstand einsetzen, wenn es sich richtig anfühlt. Im Allgemeinen würde ich sagen, dass die meisten get/set -Eigenschaften nicht viel Logik enthalten und sehr wenige, wenn überhaupt, unerwartete Nebenwirkungen haben. Wenn das Lesen eines Eigenschaftswerts das Aufrufen eines Dienstes oder das Eingeben von Eingaben eines Benutzers erfordert, um das angeforderte Objekt zu erstellen, würde ich es in eine Methode einschließen und es eher als BuildXyz() und nicht als GetXyz() bezeichnen.

17
jeremyalan

Verwenden Sie Eigenschaften in C #, nicht Get-/Set-Methoden. Sie sind für Ihre Bequemlichkeit da und es ist idiomatisch.

Was Ihre beiden C # -Beispiele angeht, so ist eines einfach syntaktischer Zucker für das andere. Verwenden Sie die Eigenschaft auto, wenn Sie nur einen einfachen Wrapper für eine Instanzvariable benötigen. Verwenden Sie die Vollversion, wenn Sie im Getter und/oder Setter Logik hinzufügen müssen.

12
Ed S.

Bevorzugen Sie in C # Eigenschaften, um private Felder für get und/oder set verfügbar zu machen. Die von Ihnen erwähnte Form ist eine Autoposition, bei der get und set automatisch ein verstecktes Pivot-Backing-Feld für Sie erzeugen. 

Ich bevorzuge automatische Eigenschaften, wenn möglich, aber Sie sollten niemals ein Set/Get-Methodenpaar in C # verwenden.

5
public string Name { get; set; }

Dies ist einfach eine automatisch implementierte Eigenschaft und entspricht technisch einer normalen Eigenschaft. Ein Hintergrundfeld wird beim Kompilieren erstellt.

Alle Eigenschaften werden schließlich in Funktionen konvertiert, sodass die tatsächliche kompilierte Implementierung letztendlich mit der in Java gewohnten übereinstimmt.

Verwenden Sie automatisch implementierte Eigenschaften, wenn Sie keine bestimmten Vorgänge im Hintergrundfeld ausführen müssen. Verwenden Sie sonst eine normale Eigenschaft. Verwenden Sie Get- und Set-Funktionen, wenn die Operation Nebenwirkungen hat oder rechenintensiv ist. Verwenden Sie Eigenschaften.

5
Steven Jeuris

Lassen Sie mich zunächst versuchen zu erklären, was Sie geschrieben haben:

// private member -- not a property
private string name;

/// public method -- not a property
public void setName(string name) {
   this.name = name;
}

/// public method -- not a property
public string getName() {
   return this.name;
}

// yes it is property structure before .Net 3.0
private string name;
public string Name {
   get { return name; }
   set { name = value; }
}

Diese Struktur wird heutzutage auch verwendet, ist jedoch am besten geeignet, wenn Sie einige zusätzliche Funktionen ausführen möchten. Wenn beispielsweise ein Wert festgelegt ist, können Sie ihn analysieren, um ihn zu aktivieren, und ihn zur privaten Verwendung in einem privaten Mitglied speichern.

Mit .net Framework 3.0

// this style is introduced, which is more common, and suppose to be best
public string Name { get; set; }

//You can more customize it
public string Name
{
    get;
    private set;    // means value could be set internally, and accessed through out
}

Wünsche dir viel Glück in C #

5
Waqas Raja

Unabhängig davon, auf welche Weise Sie in C # wählen, ist das Endergebnis das gleiche. Sie erhalten eine Hintergrundvariable mit separaten Getter- und Setter-Methoden. Durch die Verwendung von Eigenschaften befolgen Sie bewährte Vorgehensweisen. Daher ist es eine Frage, wie ausführlich Sie sein möchten. 

Persönlich würde ich auto-properties auswählen, die letzte Version: public string Name { get; set; }, da sie den geringsten Speicherplatz beansprucht. Sie können diese auch in Zukunft erweitern, wenn Sie etwas wie Validierung hinzufügen möchten.

4
Paul Sasik

Wenn immer möglich, bevorzuge ich öffentlichen string Name { get; set; }, da er knapp und leicht lesbar ist. Es kann jedoch Zeiten geben, in denen dies erforderlich ist

private string name;

public string Name {
   get { return name; }
   set { name = value; }
}
4
SquidScareMe

In C # ist der bevorzugte Weg eher durch Eigenschaften als durch getX()- und setX()-Methoden. Beachten Sie auch, dass für C # nicht erforderlich ist, dass Eigenschaften sowohl ein Get als auch ein Set haben. Sie können Get-Only-Eigenschaften und Set-Only-Eigenschaften haben. 

public boolean MyProperty
{
    get { return something; }
}

public boolean MyProperty
{
    set { this.something = value; }
}
4
Zach Johnson

Wie erwähnt, führen alle diese Ansätze zum gleichen Ergebnis. Das Wichtigste ist, dass Sie eine Konvention wählen und dabei bleiben. Ich bevorzuge die letzten beiden Immobilienbeispiele.

3
jlafay

verwenden Sie wie die meisten Antworten hier die automatischen Eigenschaften. Intuitive, weniger Codezeilen und es ist sauberer. Wenn Sie Ihre Klasse serialisieren sollten, markieren Sie das Klasse [Serializable]/mit dem [DataConract]-Attribut. Und wenn Sie [DataContract] verwenden, markieren Sie das Mitglied mit 

[DataMember(Name="aMoreFriendlyName")]
public string Name { get; set; }

Der private oder öffentliche Setter hängt von Ihren Vorlieben ab. 

Beachten Sie auch, dass für automatische Eigenschaften sowohl Getter als auch Setter (öffentlich oder privat) erforderlich sind.

/*this is invalid*/
public string Name 
{ 
    get; 
   /* setter omitted to prove the point*/
}

Wenn Sie nur get/set haben möchten, erstellen Sie alternativ selbst ein Hintergrundfeld

2
ram

Welches sollte ich verwenden, und welche sind die Vorbehalte oder Feinheiten, die mit jedem Ansatz verbunden sind?

Bei den Eigenschaften gibt es eine Einschränkung, die bisher noch nicht erwähnt wurde: Bei Eigenschaften können Sie keine Parametrisierung Ihrer Getter oder Setter vornehmen.

Stellen Sie sich zum Beispiel vor, Sie möchten Listenelemente abrufen und gleichzeitig einen Filter anwenden. Mit einer get-Methode könnten Sie so etwas schreiben:

obj.getItems(filter);

Im Gegensatz dazu müssen Sie bei einer Eigenschaft zuerst alle Elemente zurückgeben 

obj.items

anschließend wenden Sie den Filter im nächsten Schritt an, oder Sie müssen dedizierte Eigenschaften hinzufügen, die Elemente nach verschiedenen Kriterien filtern, wodurch Ihre API bald aufgebläht wird:

obj.itemsFilteredByX
obj.itemsFilteredByY

Was manchmal lästig sein kann, ist, wenn Sie mit einer Eigenschaft begonnen haben, z. obj.items und entdeckte später, dass eine Getter- oder Setter-Parametrisierung erforderlich ist oder den Klassen-API-Benutzern die Arbeit erleichtern würde. Sie müssen jetzt entweder Ihre API umschreiben und alle Stellen in Ihrem Code ändern, die auf diese Eigenschaft zugreifen, oder eine alternative Lösung finden. Im Gegensatz dazu kann mit einer Get-Methode, z. obj.getItems(), Sie können die Signatur Ihrer Methode einfach erweitern, um ein optionales "Konfigurations" -Objekt zu akzeptieren, z. obj.getItems(options), ohne alle Orte neu schreiben zu müssen, die Ihre Methode aufrufen.

Allerdings sind (automatisch implementierte) Eigenschaften in C # immer noch sehr nützliche Abkürzungen (aus den verschiedenen Gründen, die hier genannt werden), da die Parametrisierung meistens nicht erforderlich ist.

0
B12Toaster