Ich sehe viele Beispielcodes für C # -Klassen, die dies tun:
public class Point {
public int x { get; set; }
public int y { get; set; }
}
Oder in älterem Code dasselbe mit einem expliziten privaten Sicherungswert und ohne die neuen automatisch implementierten Eigenschaften:
public class Point {
private int _x;
private int _y;
public int x {
get { return _x; }
set { _x = value; }
}
public int y {
get { return _y; }
set { _y = value; }
}
}
Meine Frage ist warum. Gibt es einen funktionalen Unterschied zwischen dem oben genannten und dem öffentlichen Erstellen dieser Mitgliederfelder wie unten?
public class Point {
public int x;
public int y;
}
Um es klar auszudrücken, ich verstehe den Wert von Gettern und Setzern, wenn Sie eine Übersetzung der zugrunde liegenden Daten vornehmen müssen. Aber in Fällen, in denen Sie nur die Werte weitergeben, scheint es unnötig ausführlich zu sein.
quelle
Es ist auch viel einfacher, es später zu ändern:
public int x { get; private set; }
quelle
Es kapselt das Einstellen und Zugreifen dieser Mitglieder. Wenn ein Entwickler für den Code in einiger Zeit die Logik ändern muss, wenn auf ein Mitglied zugegriffen oder festgelegt wird, kann dies ohne Änderung des Vertrags der Klasse erfolgen.
quelle
point.x = 1;
und gutpoint.x
funktionieren.Die Idee ist, dass selbst wenn sich die zugrunde liegende Datenstruktur ändern muss, die öffentliche Schnittstelle zur Klasse nicht geändert werden muss.
C # kann Eigenschaften und Variablen manchmal unterschiedlich behandeln. Beispielsweise können Sie Eigenschaften nicht als ref- oder out-Parameter übergeben . Wenn Sie also aus irgendeinem Grund die Datenstruktur ändern müssen und öffentliche Variablen verwendet haben und jetzt Eigenschaften verwenden müssen, muss sich Ihre Schnittstelle ändern, und jetzt wird der Code, der auf die Eigenschaft x zugreift, möglicherweise nicht mehr so kompiliert, wie er war, als er variabel war x:
Point pt = new Point(); if(Int32.TryParse(userInput, out pt.x)) { Console.WriteLine("x = {0}", pt.x); Console.WriteLine("x must be a public variable! Otherwise, this won't compile."); }
Durch die Verwendung von Eigenschaften von Anfang an wird dies vermieden, und Sie können die zugrunde liegende Implementierung beliebig optimieren, ohne den Clientcode zu beschädigen.
quelle
Mit Setter and Getter können Sie eine zusätzliche Abstraktionsschicht hinzufügen. In reinem OOP sollten Sie immer über die Schnittstelle, die sie der Außenwelt zur Verfügung stellen, auf die Objekte zugreifen ...
Betrachten Sie diesen Code, der Sie in asp.net speichert und der ohne die von den Setzern und Gettern bereitgestellte Abstraktionsebene nicht möglich wäre:
class SomeControl { private string _SomeProperty ; public string SomeProperty { if ( _SomeProperty == null ) return (string)Session [ "SomeProperty" ] ; else return _SomeProperty ; } }
quelle
Da automatisch implementierte Getter denselben Namen für die Eigenschaft und die tatsächlichen privaten Speichervariablen haben. Wie können Sie es in Zukunft ändern? Ich denke, der Punkt, der gesagt wird, ist, dass Sie das automatisch implementierte anstelle des Feldes verwenden, damit Sie es in Zukunft ändern können, falls Sie Logik zu Getter und Setter hinzufügen müssen.
Zum Beispiel:
public string x { get; set; }
und zum Beispiel verwenden Sie das xa bereits oft und möchten Ihren Code nicht brechen.
Wie ändere ich den Auto Getter Setter? Zum Beispiel erlaubst du für Setter nur das Einstellen eines gültigen Telefonnummernformats ... Wie änderst du den Code so, dass nur die Klasse geändert werden soll?
Meine Idee ist, eine neue private Variable hinzuzufügen und den gleichen x Getter und Setter hinzuzufügen.
private string _x; public string x { get {return _x}; set { if (Datetime.TryParse(value)) { _x = value; } }; }
Ist es das, was Sie damit meinen, es flexibel zu machen?
quelle
Zu berücksichtigen ist auch die Auswirkung des Wechsels zu öffentlichen Mitgliedern in Bezug auf Bindung und Serialisierung. Beide basieren häufig auf öffentlichen Eigenschaften, um Werte abzurufen und festzulegen.
quelle
Sie können auch Haltepunkte für Getter und Setter setzen, jedoch nicht für Felder.
quelle
AFAIK die generierte CIL-Schnittstelle ist anders. Wenn Sie ein öffentliches Mitglied in eine Eigenschaft ändern, ändern Sie die öffentliche Schnittstelle und müssen jede Datei neu erstellen, die diese Klasse verwendet. Dies ist nicht erforderlich, wenn Sie nur die Implementierung der Getter und Setter ändern.
quelle
Wenn Sie nur Felder öffentlich machen, können Sie möglicherweise zu einem anämischeren Domänenmodell gelangen .
Mit freundlichen Grüßen
quelle
Es ist auch erwähnenswert, dass Sie Auto Properties nicht schreibgeschützt machen und sie nicht inline initialisieren können. Beides möchte ich in einer zukünftigen Version von .NET sehen, aber ich glaube, Sie können beides in .NET 4.0 nicht tun.
Ich verwende heutzutage nur dann ein Hintergrundfeld mit Eigenschaften, wenn meine Klasse INotifyPropertyChanged implementiert und ich das Ereignis OnPropertyChanged auslösen muss, wenn eine Eigenschaft geändert wird.
Auch in diesen Situationen setze ich die Hintergrundfelder direkt, wenn Werte von einem Konstruktor übergeben werden (es ist nicht erforderlich, das OnPropertyChangedEvent (das zu diesem Zeitpunkt ohnehin NULL wäre) auszulösen, wo immer ich die Eigenschaft selbst verwende.
quelle
Sie wissen nie, ob Sie später möglicherweise keine Übersetzung der Daten benötigen. Sie sind darauf vorbereitet, wenn Sie Ihre Mitglieder verstecken. Benutzer Ihrer Klasse werden es nicht bemerken, wenn Sie die Übersetzung hinzufügen, da die Benutzeroberfläche dieselbe bleibt.
quelle
Der größte Unterschied besteht darin, dass Sie bei jeder Änderung Ihrer internen Struktur die Getter und Setter unverändert beibehalten und ihre interne Logik ändern können, ohne die Benutzer Ihrer API zu verletzen.
quelle
Wenn Sie in diesem Fall ändern müssen, wie Sie x und y erhalten, können Sie die Eigenschaften später hinzufügen. Das finde ich am verwirrendsten. Wenn Sie öffentliche Mitgliedsvariablen verwenden, können Sie diese später problemlos in eine Eigenschaft ändern und private Variablen mit den Namen _x und _y verwenden, wenn Sie den Wert intern speichern müssen.
quelle
quelle
Durch Hinzufügen von Getter und Setter wird die Variable zu einer Eigenschaft wie beim Arbeiten in Wpf / C #.
Wenn es sich nur um eine öffentliche Mitgliedsvariable handelt, kann von XAML nicht darauf zugegriffen werden, da es sich nicht um eine Eigenschaft handelt (obwohl es sich um eine öffentliche Mitgliedsvariable handelt).
Wenn es Setter und Getter hat, ist es über XAML zugänglich, da es jetzt eine Eigenschaft ist.
quelle
Setter und Getter sind im Prinzip schlecht (sie sind ein schlechter OO-Geruch - ich werde aufhören zu sagen, dass sie ein Anti-Muster sind, weil sie manchmal wirklich notwendig sind).
Nein, es gibt technisch keinen Unterschied, und wenn ich heutzutage wirklich den Zugriff auf ein Objekt teilen möchte, mache ich es gelegentlich öffentlich endgültig, anstatt einen Getter hinzuzufügen.
Die Art und Weise, wie Setter und Getter "verkauft" wurden, ist, dass Sie möglicherweise wissen müssen, dass jemand einen Wert erhält oder einen ändert - was nur bei Primitiven Sinn macht.
Eigenschaftenbeutelobjekte wie DAOs, DTOs und Anzeigeobjekte sind von dieser Regel ausgeschlossen, da dies keine Objekte in einer echten "OO Design" -Bedeutung des Wortes "Objekt" sind. (Sie denken nicht daran, "Nachrichten an ein DAO weiterzuleiten", es ist einfach ein Stapel von Attribut / Wert-Paaren).
quelle