Ich nehme gerade an einer C # -Klasse teil und versuche herauszufinden, wie ich am besten vorgehen kann. Ich habe einen Java-Hintergrund und bin daher nur mit den Best Practices von Java vertraut. Ich bin ein C # Neuling!
Wenn ich in Java ein Privateigentum 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 Vorbehalte oder Feinheiten sind mit jedem Ansatz verbunden? Beim Erstellen von Klassen befolge ich allgemeine Best Practices, die ich aus Java kenne (insbesondere das Lesen von Effective Java). So bevorzuge ich zum Beispiel die Unveränderlichkeit (Setter nur bei Bedarf zur Verfügung stellen). Ich bin nur gespannt, wie diese Praktiken zu den verschiedenen Möglichkeiten passen, Setter und Getter in C # bereitzustellen. Wie würde ich Best Practices aus der Java-Welt in C # übersetzen?
BEARBEITEN
Ich habe dies als Kommentar zu Jon Skeets Antwort gepostet, aber dann wurde es lang:
Was ist mit einer nicht trivialen Eigenschaft (dh mit möglicherweise erheblicher Verarbeitung und Validierung)? Könnte ich es trotzdem über eine öffentliche Eigenschaft verfügbar machen, aber mit der in get
und gekapselten Logik set
? Warum sollte / sollte ich dies tun, wenn ich dedizierte Setter- und Getter-Methoden habe (mit zugehöriger Verarbeitungs- und Validierungslogik)?
quelle
public int Y { get; } = y;
) haben.Wenn Sie lediglich eine Variable zum Speichern einiger Daten benötigen:
Möchten Sie es schreibgeschützt anzeigen?
Oder noch besser ...
Möchten Sie eine Wertprüfung durchführen, bevor Sie die Eigenschaft zuweisen?
Im Allgemeinen werden GetXyz () und SetXyz () nur in bestimmten Fällen verwendet, und Sie müssen nur Ihren Darm verwenden, wenn es sich richtig anfühlt. Im Allgemeinen würde ich sagen, dass ich erwarte, dass die meisten get / set-Eigenschaften nicht viel Logik enthalten und nur sehr wenige, wenn überhaupt, unerwartete Nebenwirkungen haben. Wenn das Lesen eines Eigenschaftswerts das Aufrufen eines Dienstes oder das Abrufen von Eingaben von einem Benutzer erfordert, um das von mir angeforderte Objekt zu erstellen, würde ich es in eine Methode einbinden und es
BuildXyz()
eher so nennen alsGetXyz()
.quelle
myList.Add()
(solange das Objekt Änderungen ausgesetzt ist, ist es veränderlich).Min
/Max
Wert haben ? Sie möchten das sicherstellenMax > Min
? EinSetRange(Min, Max)
könnte Sinn machen, aber wie werden Sie diese Werte dann zurücklesen? Schreibgeschützte Min / Max-Eigenschaften? Das Auslösen von Ausnahmen für ungültige Eingaben scheint der sauberste Weg zu sein, um damit umzugehen.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 betrifft, so ist eines einfach syntaktischer Zucker für das andere. Verwenden Sie die Eigenschaft auto, wenn Sie lediglich einen einfachen Wrapper um eine Instanzvariable benötigen. Verwenden Sie die Vollversion, wenn Sie dem Getter und / oder Setter Logik hinzufügen müssen.
quelle
In C # bevorzugen Sie Eigenschaften zum Offenlegen privater Felder für get und / oder set. Das von Ihnen erwähnte Formular ist eine Autoproperty, bei der das Abrufen und Setzen automatisch ein verstecktes Pivot-Backing-Feld für Sie generiert.
Ich bevorzuge Auto-Eigenschaften, wenn dies möglich ist, aber Sie sollten niemals ein Set / Get-Methodenpaar in C # ausführen.
quelle
Dies ist einfach eine automatisch implementierte Eigenschaft und entspricht technisch einer normalen Eigenschaft. Beim Kompilieren wird ein Hintergrundfeld erstellt.
Alle Eigenschaften werden schließlich in Funktionen konvertiert, sodass die tatsächlich kompilierte Implementierung am Ende dieselbe ist, wie Sie es in Java gewohnt sind.
Verwenden Sie automatisch implementierte Eigenschaften, wenn Sie keine bestimmten Vorgänge für das Sicherungsfeld ausführen müssen. Verwenden Sie andernfalls eine gewöhnliche Eigenschaft. Verwenden Sie get- und set-Funktionen, wenn die Operation Nebenwirkungen hat oder rechenintensiv ist. Verwenden Sie ansonsten Eigenschaften.
quelle
Unabhängig davon, welchen Weg Sie in C # wählen, ist das Endergebnis dasselbe. Sie erhalten eine Backinng-Variable mit separaten Getter- und Setter-Methoden. Wenn Sie Eigenschaften verwenden, befolgen Sie die Best Practices. Es kommt also darauf an, wie ausführlich Sie werden möchten.
Persönlich würde ich Auto-Eigenschaften wählen, die letzte Version :
public string Name { get; set; }
, da sie am wenigsten Platz beanspruchen. Und Sie können diese in Zukunft jederzeit erweitern, wenn Sie eine Validierung hinzufügen müssen.quelle
Wann immer möglich, bevorzuge ich die Öffentlichkeit,
string Name { get; set; }
da sie knapp und leicht lesbar ist. Es kann jedoch Zeiten geben, in denen dies erforderlich istquelle
In C # die bevorzugte Art und Weise ist durch Eigenschaften statt
getX()
undsetX()
Methoden. Beachten Sie außerdem, dass C # nicht erfordert, dass Eigenschaften sowohl ein get als auch ein set haben. Sie können nur get-Eigenschaften und nur set-Eigenschaften haben.quelle
Lassen Sie mich zunächst versuchen zu erklären, was Sie geschrieben haben:
Diese Struktur wird heutzutage auch verwendet, ist jedoch am besten geeignet, wenn Sie zusätzliche Funktionen ausführen möchten. Wenn beispielsweise ein Wert festgelegt ist, können Sie ihn analysieren, um ihn zu aktivieren und als privates Element für den internen Gebrauch zu speichern.
Mit .net Framework 3.0
Wünsche dir mehr Glück in C #
quelle
Wie bereits erwähnt, führen alle diese Ansätze zum gleichen Ergebnis. Das Wichtigste ist, dass Sie eine Konvention auswählen und dabei bleiben. Ich bevorzuge die letzten beiden Eigenschaftsbeispiele.
quelle
Verwenden Sie wie die meisten Antworten hier die automatischen Eigenschaften. Intuitiv, weniger Codezeilen und sauberer. Wenn Sie Ihre Klasse serialisieren sollten, markieren Sie das Attribut class
[Serializable]
/ with[DataConract]
. Und wenn Sie verwenden,[DataContract]
markieren Sie das Mitglied mitPrivater oder öffentlicher Setter hängt von Ihrer Präferenz ab.
Beachten Sie auch, dass für automatische Eigenschaften sowohl Getter als auch Setter (öffentlich oder privat) erforderlich sind.
Wenn Sie nur get / set möchten, erstellen Sie alternativ selbst ein Hintergrundfeld
quelle
Wenn Sie sich für Eigenschaften entscheiden, gibt es eine Einschränkung, die noch nicht erwähnt wurde: Bei Eigenschaften können Sie Ihre Getter oder Setter nicht parametrisieren.
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 wie:
Im Gegensatz dazu müssen Sie bei einer Eigenschaft zuerst alle Elemente zurückgeben
Wenden Sie den Filter dann im nächsten Schritt an, oder Sie müssen dedizierte Eigenschaften hinzufügen, die nach verschiedenen Kriterien gefilterte Elemente verfügbar machen, wodurch Ihre API bald aufgebläht wird:
Was manchmal störend sein kann, ist, wenn Sie mit einer Eigenschaft begonnen haben, z. B.
obj.items
und später festgestellt haben, dass eine Getter- oder Setter-Parametrisierung erforderlich ist oder dem Benutzer der Klassen-API die Arbeit erleichtern würde. Sie müssten jetzt entweder Ihre API neu schreiben und alle Stellen in Ihrem Code ändern, die auf diese Eigenschaft zugreifen, oder eine alternative Lösung finden. Im Gegensatz dazu können Sie mit einer get-Methode z. B.obj.getItems()
einfach die Signatur Ihrer Methode erweitern, um ein optionales "Konfigurations" -Objekt zu akzeptieren, zobj.getItems(options)
ohne alle Stellen neu schreiben zu müssen, die Ihre Methode aufrufen.Abgesehen davon sind (automatisch implementierte) Eigenschaften in C # immer noch sehr nützliche Verknüpfungen (aus den verschiedenen hier genannten Gründen), da die meiste Zeit möglicherweise keine Parametrisierung erforderlich ist - aber diese Einschränkung bleibt bestehen.
quelle