Was unterscheidet ein Feld in C # von einer Eigenschaft und wann sollte ein Feld anstelle einer Eigenschaft verwendet werden?
Eigenschaften machen Felder verfügbar. Felder sollten (fast immer) für eine Klasse privat gehalten und über get- und set-Eigenschaften aufgerufen werden. Eigenschaften bieten eine Abstraktionsebene, mit der Sie die Felder ändern können, ohne dass sich dies auf die Art und Weise auswirkt, in der die Elemente, die Ihre Klasse verwenden, auf sie zugreifen.
public class MyClass
{
// this is a field. It is private to your class and stores the actual data.
private string _myField;
// this is a property. When accessed it uses the underlying field,
// but only exposes the contract, which will not be affected by the underlying field
public string MyProperty
{
get
{
return _myField;
}
set
{
_myField = value;
}
}
// This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
// used to generate a private field for you
public int AnotherProperty{get;set;}
}
@Kent weist darauf hin, dass Eigenschaften nicht zum Einkapseln von Feldern erforderlich sind. Sie können eine Berechnung für andere Felder durchführen oder anderen Zwecken dienen.
@GSS weist darauf hin, dass Sie beim Zugriff auf eine Eigenschaft auch andere Logik ausführen können, z. B. die Validierung. Dies ist eine weitere nützliche Funktion.
Objektorientierte Programmierprinzipien besagen, dass die internen Abläufe einer Klasse vor der Außenwelt verborgen sein sollten. Wenn Sie ein Feld verfügbar machen, legen Sie im Wesentlichen die interne Implementierung der Klasse offen. Daher umschließen wir Felder mit Eigenschaften (oder Methoden in Javas Fall), damit wir die Implementierung ändern können, ohne den Code von uns abhängig zu machen. Da wir Logik in die Eigenschaft einfügen können, können wir bei Bedarf auch Validierungslogik usw. ausführen. C # 3 hat den möglicherweise verwirrenden Begriff der Eigenschaf- ten. Dadurch können wir einfach die Eigenschaft definieren und der C # 3-Compiler generiert das private Feld für uns.
public class Person
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
public int Age{get;set;} //AutoProperty generates private field for us
}
Ein wichtiger Unterschied besteht darin, dass Schnittstellen Eigenschaften haben können, aber keine Felder. Dies unterstreicht für mich, dass Eigenschaften verwendet werden sollten, um die öffentliche Schnittstelle einer Klasse zu definieren, während Felder für die private interne Arbeitsweise einer Klasse vorgesehen sind. In der Regel erstelle ich selten öffentliche Felder und ebenso selten nicht öffentliche Eigenschaften.
Ich gebe Ihnen ein paar Beispiele für die Verwendung von Eigenschaften, mit denen sich die Zahnräder drehen können:
Mit Properties können Sie ein Ereignis auslösen, wenn der Wert der Eigenschaft geändert wird (aka. PropertyChangedEvent) oder bevor der Wert geändert wird, um das Abbrechen zu unterstützen.
Dies ist bei (direktem Zugriff auf) Felder nicht möglich.
public class Person {
private string _name;
public event EventHandler NameChanging;
public event EventHandler NameChanged;
public string Name{
get
{
return _name;
}
set
{
OnNameChanging();
_name = value;
OnNameChanged();
}
}
private void OnNameChanging(){
EventHandler localEvent = NameChanging;
if (localEvent != null) {
localEvent(this,EventArgs.Empty);
}
}
private void OnNameChanged(){
EventHandler localEvent = NameChanged;
if (localEvent != null) {
localEvent(this,EventArgs.Empty);
}
}
}
Da viele von ihnen die technischen Vor- und Nachteile von Properties
und Field
erläutert haben, ist es an der Zeit, sich in Echtzeit mit Beispielen zu befassen.
1. Mit Eigenschaften können Sie die schreibgeschützte Zugriffsebene festlegen .
Betrachten Sie den Fall von dataTable.Rows.Count
und dataTable.Columns[i].Caption
. Sie kommen aus der Klasse DataTable
und beide sind für uns öffentlich. Der Unterschied in der Zugriffsebene zu ihnen besteht darin, dass wir den Wert nicht auf dataTable.Rows.Count
setzen können, sondern auf dataTable.Columns[i].Caption
lesen und schreiben können. Ist das durch Field
möglich? Nein!!! Dies ist nur mit Properties
möglich.
public class DataTable
{
public class Rows
{
private string _count;
// This Count will be accessable to us but have used only "get" ie, readonly
public int Count
{
get
{
return _count;
}
}
}
public class Columns
{
private string _caption;
// Used both "get" and "set" ie, readable and writable
public string Caption
{
get
{
return _caption;
}
set
{
_caption = value;
}
}
}
}
2. Eigenschaften in PropertyGrid
Möglicherweise haben Sie in Visual Studio mit Button
gearbeitet. Seine Eigenschaften werden in der PropertyGrid
wie Text
, Name
usw. angezeigt. Wenn wir eine Schaltfläche ziehen und ablegen und auf die Eigenschaften klicken, wird automatisch die Klasse Button
und die Filter Properties
gefunden und in PropertyGrid
angezeigt (wobei PropertyGrid
nicht angezeigt wird) Field
, obwohl sie öffentlich sind).
public class Button
{
private string _text;
private string _name;
private string _someProperty;
public string Text
{
get
{
return _text;
}
set
{
_text = value;
}
}
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
[Browsable(false)]
public string SomeProperty
{
get
{
return _someProperty;
}
set
{
_someProperty= value;
}
}
In PropertyGrid
werden die Eigenschaften Name
und Text
angezeigt, nicht jedoch SomeProperty
. Warum??? Weil Eigenschaften Attribute akzeptieren können. Es wird nicht angezeigt, wenn [Browsable(false)]
falsch ist.
3. Kann Anweisungen innerhalb von Properties ausführen
public class Rows
{
private string _count;
public int Count
{
get
{
return CalculateNoOfRows();
}
}
public int CalculateNoOfRows()
{
// Calculation here and finally set the value to _count
return _count;
}
}
4. In Bindungsquelle können nur Eigenschaften verwendet werden
Binding Source hilft uns, die Anzahl der Codezeilen zu verringern. Fields
werden von BindingSource
nicht akzeptiert. Wir sollten dafür Properties
verwenden.
5. Debugging-Modus
Stellen Sie sich vor, wir verwenden Field
, um einen Wert zu speichern. Irgendwann müssen wir debuggen und prüfen, wo der Wert für dieses Feld null wird. Wenn die Anzahl der Codezeilen mehr als 1000 beträgt, ist dies schwierig. In solchen Situationen können wir Property
verwenden und den Debug-Modus in Property
festlegen.
public string Name
{
// Can set debug mode inside get or set
get
{
return _name;
}
set
{
_name = value;
}
}
Ein Feld ist eine Variable, die direkt in einer Klasse oder Struktur deklariert wird. Eine Klasse oder Struktur kann Instanzfelder oder statische Felder oder beides enthalten. Im Allgemeinen sollten Sie Felder nur für Variablen verwenden, die über einen privaten oder geschützten Zugriff verfügen . Daten, die Ihre Klasse für Clientcode verfügbar macht , sollten über Methoden, Eigenschaften und Indexer bereitgestellt werden. Indem Sie diese Konstrukte für den indirekten Zugriff auf interne Felder verwenden, können Sie sich vor ungültigen Eingabewerten schützen.
Eine Eigenschaft ist ein Member, der einen flexiblen Mechanismus zum Lesen, Schreiben oder Berechnen des Werts eines privaten Felds bereitstellt. Eigenschaften können verwendet werden, als wären sie öffentliche Datenelemente, es handelt sich jedoch tatsächlich um spezielle Methoden, die als Accessoren bezeichnet werden. Dies ermöglicht einen einfachen Zugriff auf Daten und fördert dennoch die Sicherheit und Flexibilität von Methoden . Mithilfe von Eigenschaften kann eine Klasse eine öffentliche Methode zum Abrufen und Festlegen von Werten bereitstellen, während der Implementierungs- oder Überprüfungscode ausgeblendet wird. Ein get-Eigenschafts-Accessor wird verwendet, um den Eigenschaftswert zurückzugeben, und ein set-Accessor wird verwendet, um einen neuen Wert zuzuweisen.
Eigenschaften haben den Hauptvorteil, dass Sie den Zugriff auf Daten eines Objekts ändern können, ohne die öffentliche Schnittstelle zu beschädigen. Wenn Sie beispielsweise eine zusätzliche Validierung hinzufügen oder ein gespeichertes Feld in ein berechnetes Feld ändern müssen, können Sie dies problemlos tun, wenn Sie das Feld ursprünglich als Eigenschaft verfügbar gemacht haben. Wenn Sie ein Feld nur direkt verfügbar gemacht hätten, müssten Sie die öffentliche Schnittstelle Ihrer Klasse ändern, um die neue Funktionalität hinzuzufügen. Diese Änderung würde bestehende Clients beschädigen und eine Neukompilierung erforderlich machen, bevor sie die neue Version Ihres Codes verwenden können.
Wenn Sie eine Klassenbibliothek schreiben, die für den breiten Verbrauch ausgelegt ist (wie das .NET Framework, das von Millionen von Menschen verwendet wird), kann dies ein Problem sein. Wenn Sie jedoch eine Klasse schreiben, die intern in einer kleinen Codebasis (z. B. <= 50 KByte) verwendet wird, ist dies keine große Sache, da Ihre Änderungen niemanden nachteilig beeinflussen würden. In diesem Fall kommt es wirklich nur auf die persönlichen Vorlieben an.
Im Hintergrund wird eine Eigenschaft in Methoden kompiliert. So wird eine Name
-Eigenschaft in get_Name()
und set_Name(string value)
kompiliert. Sie können dies sehen, wenn Sie den kompilierten Code studieren. Daher entsteht bei deren Verwendung ein (sehr) geringer Performance-Aufwand. Normalerweise verwenden Sie eine Eigenschaft immer, wenn Sie ein Feld nach außen freigeben, und Sie verwenden es häufig intern, wenn Sie den Wert überprüfen müssen.
Eigenschaften unterstützen asymmetrischen Zugriff, d. H. Sie können entweder einen Getter und einen Setter oder nur einen der beiden haben. Ebenso unterstützen Eigenschaften die individuelle Zugänglichkeit für Getter/Setter. Felder sind immer symmetrisch, d. H. Sie können den Wert immer sowohl abrufen als auch festlegen. Eine Ausnahme bilden schreibgeschützte Felder, die nach der Initialisierung offensichtlich nicht mehr gesetzt werden können.
Eigenschaften können sehr lange ausgeführt werden, Nebenwirkungen haben und sogar Ausnahmen auslösen. Felder sind schnell, ohne Nebenwirkungen und werden niemals Ausnahmen auslösen. Aufgrund von Nebenwirkungen kann eine Eigenschaft für jeden Aufruf einen anderen Wert zurückgeben (wie dies für DateTime.Now der Fall sein kann, d. H. DateTime.Now ist nicht immer gleich DateTime.Now). Felder geben immer den gleichen Wert zurück.
Felder können für out/ref-Parameter verwendet werden, Eigenschaften möglicherweise nicht. Eigenschaften unterstützen zusätzliche Logik - dies kann unter anderem zum Implementieren von verzögertem Laden verwendet werden.
Eigenschaften unterstützen eine Abstraktionsebene, indem sie alles einkapseln, was es bedeutet, den Wert abzurufen/festzulegen.
Verwenden Sie in den meisten Fällen Eigenschaften, vermeiden Sie jedoch Nebenwirkungen.
Wenn Ihre private Variable (Feld) für Objekte Ihrer Klasse aus anderen Klassen zugänglich sein soll, müssen Sie Eigenschaften für diese Variablen erstellen.
zum Beispiel, wenn ich Variablen mit den Namen "id" und "name" habe, die privat sind, es aber Situationen geben kann, in denen diese Variable für Lese-/Schreibvorgänge außerhalb der Klasse benötigt wird. In dieser Situation kann Eigenschaft mir helfen, diese Variable abhängig von dem für die Eigenschaft definierten get/set zum Lesen/Schreiben zu bringen. Eine Eigenschaft kann schreibgeschützt/schreibgeschützt/schreibgeschützt sein.
hier ist die Demo
class Employee
{
// Private Fields for Employee
private int id;
private string name;
//Property for id variable/field
public int EmployeeId
{
get
{
return id;
}
set
{
id = value;
}
}
//Property for name variable/field
public string EmployeeName
{
get
{
return name;
}
set
{
name = value;
}
}
}
class MyMain
{
public static void Main(string [] args)
{
Employee aEmployee = new Employee();
aEmployee.EmployeeId = 101;
aEmployee.EmployeeName = "Sundaran S";
}
}
Die zweite Frage hier: "Wann soll ein Feld anstelle einer Eigenschaft verwendet werden?" Wird nur kurz in diese andere Antwort und irgendwie auch diese angesprochen, aber nicht wirklich viel Detail.
Im Allgemeinen sprechen alle anderen Antworten für gutes Design: Belichten Sie lieber Eigenschaften als Felder. Sie werden wahrscheinlich nicht regelmäßig sagen : "Wow, stellen Sie sich vor, wie viel schlimmer es wäre, wenn ich dieses Feld anstelle eines Grundstücks gemacht hätte." Es ist so viel seltener, an eine Situation zu denken, in der man sagen würde: "Wow, Gott sei Dank, ich habe hier ein Feld anstelle eines Grundstücks verwendet."
Aber es gibt einen Vorteil, den Felder gegenüber Eigenschaften haben, und das ist ihre Fähigkeit, als "ref"/"out" -Parameter verwendet zu werden. Angenommen, Sie haben eine Methode mit der folgenden Signatur:
public void TransformPoint(ref double x, ref double y);
angenommen, Sie möchten diese Methode verwenden, um ein Array zu transformieren, das wie folgt erstellt wurde:
System.Windows.Point[] points = new Point[1000000];
Initialize(points);
Hier ist meiner Meinung nach der schnellste Weg, da X und Y Eigenschaften sind:
for (int i = 0; i < points.Length; i++)
{
double x = points[i].X;
double y = points[i].Y;
TransformPoint(ref x, ref y);
points[i].X = x;
points[i].Y = y;
}
Und das wird ziemlich gut! Wenn Sie keine Messungen haben, die das Gegenteil beweisen, gibt es keinen Grund, einen Gestank zu werfen. Aber ich glaube, es ist technisch nicht garantiert, dass es so schnell ist:
internal struct MyPoint
{
internal double X;
internal double Y;
}
// ...
MyPoint[] points = new MyPoint[1000000];
Initialize(points);
// ...
for (int i = 0; i < points.Length; i++)
{
TransformPoint(ref points[i].X, ref points[i].Y);
}
Bei einigen Messungen selbst benötigt die Version mit Feldern ungefähr 61% der Zeit als die Version mit Eigenschaften (.NET 4.6, Windows 7, x64, Freigabemodus, kein Debugger angehängt). Je teurer die Methode TransformPoint
wird, desto geringer wird der Unterschied. Um dies selbst zu wiederholen, führen Sie die erste auskommentierte und nicht auskommentierte Zeile aus.
Selbst wenn es keine Leistungsvorteile für die oben genannten gibt, gibt es andere Stellen, an denen die Verwendung von ref- und out-Parametern von Vorteil sein kann, z. B. beim Aufrufen von Interlocked oder Volatile Methodenfamilie. Hinweis: Falls dies für Sie neu ist, ist Volatile im Grunde eine Möglichkeit, dasselbe Verhalten wie mit dem Schlüsselwort volatile
zu erreichen. Als solches, wie volatile
, löst es nicht auf magische Weise alle Sicherheitslücken, wie der Name vermuten lässt.
Ich möchte auf keinen Fall den Eindruck erwecken, als würde ich dafür plädieren, dass Sie "oh, ich sollte anfangen, Felder anstelle von Eigenschaften freizulegen". Der Punkt ist, dass, wenn Sie diese Member regelmäßig in Aufrufen verwenden müssen, die "ref" - oder "out" -Parameter annehmen, insbesondere in einem einfachen Wertetyp, der wahrscheinlich nie eines der Mehrwertelemente von Eigenschaften benötigt. Ein Argument kann vorgebracht werden.
Diese Seite auf MSDN enthält einen Vergleich und Tipps, die Sie verwenden sollten, wenn:
https://msdn.Microsoft.com/en-us/library/9d65as2e (v = vs.90) .aspx
Technisch glaube ich nicht, dass es einen Unterschied gibt, weil Eigenschaften nur Wrapper um vom Benutzer erstellte oder vom Compiler automatisch erstellte Felder sind. Der Zweck von Eigenschaften besteht darin, die Kapselung zu erzwingen und eine einfache methodenähnliche Funktion anzubieten. Es ist nur eine schlechte Praxis, Felder als öffentlich zu deklarieren, aber es gibt keine Probleme.
Wenn Sie Thread-Primitive verwenden, müssen Sie Felder verwenden. Eigenschaften können Ihren Thread-Code beschädigen. Abgesehen davon ist das, was Cory sagte, richtig.
(Dies sollte eigentlich ein Kommentar sein, aber ich kann keinen Kommentar posten, bitte entschuldigen Sie, wenn er nicht als Beitrag geeignet ist.).
Ich habe einmal an einem Ort gearbeitet, an dem die empfohlene Vorgehensweise darin bestand, öffentliche Felder anstelle von Eigenschaften zu verwenden, wenn die entsprechende Eigenschaft def nur auf ein Feld zugegriffen hätte, wie in:
get { return _afield; }
set { _afield = value; }
Ihre Argumentation war, dass das öffentliche Feld später bei Bedarf in eine Immobilie umgewandelt werden könnte. Es kam mir damals etwas seltsam vor. Nach diesen Beiträgen zu urteilen, scheinen auch hier nicht viele zuzustimmen. Was könnten Sie gesagt haben, um zu versuchen, Dinge zu ändern?
Bearbeiten: Ich sollte hinzufügen, dass die gesamte Codebasis an diesem Ort zur gleichen Zeit kompiliert wurde, so dass sie gedacht haben könnten, dass das Ändern der öffentlichen Schnittstelle von Klassen (durch Ändern eines öffentlichen Felds in eine Eigenschaft) kein Problem war.
Felder sind gewöhnliche Mitgliedsvariablen oder Mitgliedsinstanzen einer Klasse. Eigenschaften sind ein Abstraktion zum Abrufen und Festlegen ihrer Werte. Eigenschaften werden auch als Accessoren bezeichnet, da sie die Möglichkeit bieten, ein Feld zu ändern und abzurufen, wenn Sie ein Feld in der Klasse als privat verfügbar machen. Im Allgemeinen sollten Sie Ihre Mitgliedsvariablen als privat deklarieren und dann Eigenschaften für sie deklarieren oder definieren.
class SomeClass
{
int numbera; //Field
//Property
public static int numbera { get; set;}
}
Mithilfe von Eigenschaften können Sie beim Festlegen von Werten auch Logik verwenden.
Sie können also sagen, dass Sie nur dann einen Wert für ein ganzzahliges Feld festlegen möchten, wenn der Wert größer als x ist. Andernfalls wird eine Ausnahme ausgelöst.
Wirklich nützliche Funktion.
Traditionell werden private Felder über Getter- und Setter-Methoden gesetzt. Um den Code zu reduzieren, können Sie stattdessen mithilfe von Eigenschaften Felder festlegen.
Aus Wikipedia - Objektorientierte Programmierung :
Objektorientierte Programmierung (OOP) ist ein Programmierparadigma, das auf dem Konzept von "Objekten" basiert. Hierbei handelt es sich um Datenstrukturen, die Daten in Form von Feldern enthalten , oft als Attribute bezeichnet; und Code in Form von Prozeduren, die oft als Methoden bezeichnet werden. (Hervorhebung hinzugefügt)
Eigenschaften sind eigentlich Teil des Verhaltens eines Objekts, sollen jedoch den Verbrauchern des Objekts die Illusion/Abstraktion vermitteln, mit den Daten des Objekts zu arbeiten.
Eigenschaften kapseln Felder ein, sodass Sie den einzustellenden oder abzurufenden Wert weiter verarbeiten können. Es ist in der Regel zu viel des Guten, Eigenschaften zu verwenden, wenn Sie keine Vor- oder Nachbearbeitung für den Feldwert ausführen.
wenn Sie eine Klasse haben, die "Auto" ist. Die Eigenschaften sind Farbe, Form ..
Wobei as-Felder Variablen sind, die im Bereich einer Klasse definiert sind.
Felder sind die Variablen in Klassen. Felder sind die Daten, die Sie mithilfe von Zugriffsmodifikatoren kapseln können.
Eigenschaften ähneln Fields, da sie Zustände und die mit einem Objekt verknüpften Daten definieren.
Im Gegensatz zu einem Feld hat eine Eigenschaft eine spezielle Syntax, die steuert, wie eine Person die Daten liest und schreibt. Diese werden als get- und set-Operatoren bezeichnet. Die eingestellte Logik kann häufig zur Validierung verwendet werden.
IMO, Properties sind nur die "SetXXX ()" - "GetXXX ()" - Funktionen/Methoden/Schnittstellen-Paare, die wir zuvor verwendet haben, aber sie sind prägnanter und eleganter.
Mein Design eines Feldes ist, dass ein Feld nur von seinem Elternteil geändert werden muss, daher die Klasse. Das Ergebnis ist, dass die Variable privat wird. Um dann das Recht zu geben, die Klassen/Methoden außerhalb des Systems zu lesen, gehe ich nur mit Get durch das Eigenschaftensystem. Das Feld wird dann von der Eigenschaft abgerufen und ist schreibgeschützt! Wenn Sie es ändern möchten, müssen Sie Methoden durchgehen (zum Beispiel den Konstruktor), und ich finde, dass wir dank dieser Art, Sie zu schützen, eine bessere Kontrolle über unseren Code haben, weil wir "flanschen". Man könnte sehr wohl immer alles öffentlich machen, also jeder mögliche Fall, die Vorstellung von Variablen/Methoden/Klassen etc ... ist meiner Meinung nach nur eine Hilfe bei der Entwicklung, Pflege des Codes. Wenn zum Beispiel eine Person einen Code mit öffentlichen Feldern wieder aufnimmt, kann sie alles und damit Dinge tun, die in Bezug auf das Ziel, die Logik, warum der Code geschrieben wurde, "unlogisch" sind. Das ist meine Sichtweise.
Wenn ich ein klassisches Modell Private Field/Public Readonly-Eigenschaften verwende, sollte ich für 10 Private Fields 10 Publics-Eigenschaften schreiben! Der Code kann sehr viel schneller sein. Ich entdecke den privaten Setter und verwende jetzt nur öffentliche Eigenschaften mit einem privaten Setter. Der Setter erstellt im Hintergrund ein privates Feld.
Deshalb war mein alter klassischer Programmierstil:
public class MyClass
{
private int _id;
public int ID { get { return _id; } }
public MyClass(int id)
{
_id = id;
}
}
Mein neuer Programmierstil:
public class MyClass
{
public int ID { get; private set; }
public MyClass(int id)
{
ID = id;
}
}
Grundlegender und allgemeiner Unterschied ist:
Felder
Eigenschaften
Denken Sie darüber nach: Sie haben einen Raum und eine Tür, um diesen Raum zu betreten. Wenn Sie überprüfen möchten, wie wer hereinkommt, und Ihr Zimmer sichern möchten, sollten Sie Objekte verwenden, da diese sonst keine Tür darstellen und alle ohne Vorschriften problemlos hereinkommen
class Room {
public string sectionOne;
public string sectionTwo;
}
Room r = new Room();
r.sectionOne = "enter";
Die Leute kommen ziemlich leicht zu SectionOne, es gab keine Überprüfung
class Room
{
private string sectionOne;
private string sectionTwo;
public string SectionOne
{
get
{
return sectionOne;
}
set
{
sectionOne = Check(value);
}
}
}
Room r = new Room();
r.SectionOne = "enter";
Jetzt hast du die Person überprüft und weißt, ob sie etwas Böses bei sich hat
In den allermeisten Fällen handelt es sich um einen Eigenschaftsnamen, auf den Sie zugreifen, und nicht um einen Variablennamen (). Der Grund dafür ist, dass er als gut angesehen wird Üben Sie in .NET und insbesondere in C #, um alle Daten einer Klasse zu schützen, unabhängig davon, ob es sich um eine Instanzvariable oder eine statische Variable (Klassenvariable) handelt, da sie einer Klasse zugeordnet sind.
Schützen Sie alle Variablen mit den entsprechenden Eigenschaften, mit denen Sie festlegen und abrufen Accessoren können, und führen Sie bei Bedarf Überprüfungen durch manipulieren diese Daten.
In anderen Fällen wie Math-Klasse (System-Namespace) sind jedoch einige statische Eigenschaften in die Klasse integriert. Eine davon ist die mathematische Konstante PI
z.B. Math.PI
und da PI ein genau definiertes Datenelement ist, müssen wir nicht mehrere Kopien von PI haben, es wird immer der gleiche Wert sein. Daher werden statische Variablen manchmal verwendet, um Daten für Objekte einer Klasse freizugeben. Sie werden jedoch auch häufig für konstante Informationen verwendet, wenn Sie nur eine Kopie eines Datenelements benötigen.
Eigenschaften werden verwendet, um das Feld verfügbar zu machen. Sie verwenden Accessoren (set, get), über die die Werte der privaten Felder gelesen, geschrieben oder manipuliert werden können.
Eigenschaften benennen die Speicherorte nicht. Stattdessen verfügen sie über Accessoren, die ihre Werte lesen, schreiben oder berechnen.
Mithilfe von Eigenschaften können wir die Validierung für den Datentyp festlegen, der für ein Feld festgelegt ist.
Zum Beispiel haben wir ein privates ganzzahliges Alter, bei dem wir positive Werte zulassen sollten, da das Alter nicht negativ sein kann.
Wir können dies auf zwei Arten tun, indem wir Getter und Setter und Property verwenden.
Using Getter and Setter
// field
private int _age;
// setter
public void set(int age){
if (age <=0)
throw new Exception();
this._age = age;
}
// getter
public int get (){
return this._age;
}
Now using property we can do the same thing. In the value is a key Word
private int _age;
public int Age{
get{
return this._age;
}
set{
if (value <= 0)
throw new Exception()
}
}
Automatisch implementierte Eigenschaft Wenn keine Logik zum Abrufen und Festlegen von Accessoren vorhanden ist, können Sie die automatisch implementierte Eigenschaft verwenden.
Wenn u Diese automatisch implementierte Eigenschaftskompilierung erstellt ein privates, anonymes Feld, auf das nur über get- und set-Accessoren zugegriffen werden kann.
public int Age{get;set;}
Abstrakte Eigenschaften Eine abstrakte Klasse kann eine abstrakte Eigenschaft haben, die in der abgeleiteten Klasse implementiert werden sollte
public abstract class Person
{
public abstract string Name
{
get;
set;
}
public abstract int Age
{
get;
set;
}
}
// overriden something like this
// Declare a Name property of type string:
public override string Name
{
get
{
return name;
}
set
{
name = value;
}
}
Wir können privat eine Eigenschaft setzen. In dieser können wir privat die Eigenschaft auto setzen (setzen mit in der Klasse).
public int MyProperty
{
get; private set;
}
Mit diesem Code können Sie dasselbe erreichen. In diesem Eigenschaftssatz ist keine Funktion verfügbar, da der Wert direkt auf Feld gesetzt werden muss.
private int myProperty;
public int MyProperty
{
get { return myProperty; }
}
Eigenschaften sind eine spezielle Art von Klassenmitgliedern. In Eigenschaften verwenden wir eine vordefinierte Set- oder Get-Methode. Sie verwenden Zugriffsmethoden, mit denen wir die Werte der privaten Felder lesen, schreiben oder ändern können.
Nehmen wir zum Beispiel eine Klasse namens Employee
mit privaten Feldern für Name, Alter und Employee_Id. Wir können nicht von außerhalb der Klasse auf diese Felder zugreifen, aber wir können über Eigenschaften auf diese privaten Felder zugreifen.
Warum verwenden wir Eigenschaften?
Das Klassenfeld öffentlich zu machen und offenzulegen ist riskant, da Sie nicht kontrollieren können, was zugewiesen und zurückgegeben wird.
Um dies anhand eines Beispiels klar zu verstehen, nehmen wir eine Schülerklasse mit ID, PassMark und Name. Nun in diesem Beispiel ein Problem mit dem öffentlichen Bereich
Um dieses Problem zu beheben, verwenden wir die Methode Get and Set.
// A simple example
public class student
{
public int ID;
public int PassMark;
public string name;
}
public class Program
{
public static void Main(string[] args)
{
student s1 = new student();
s1.ID = -101; // here ID can't be -ve
s1.Name = null ; // here Name can't be null
}
}
Nun nehmen wir ein Beispiel für die Methode get und set
public class student
{
private int _ID;
private int _PassMark;
private string_name ;
// for id property
public void SetID(int ID)
{
if(ID<=0)
{
throw new exception("student ID should be greater then 0");
}
this._ID = ID;
}
public int getID()
{
return_ID;
}
}
public class programme
{
public static void main()
{
student s1 = new student ();
s1.SetID(101);
}
// Like this we also can use for Name property
public void SetName(string Name)
{
if(string.IsNullOrEmpty(Name))
{
throw new exeception("name can not be null");
}
this._Name = Name;
}
public string GetName()
{
if( string.IsNullOrEmpty(This.Name))
{
return "No Name";
}
else
{
return this._name;
}
}
// Like this we also can use for PassMark property
public int Getpassmark()
{
return this._PassMark;
}
}
Obwohl Felder und Eigenschaften ähnlich aussehen, handelt es sich um zwei völlig unterschiedliche Sprachelemente.
Felder sind der einzige Mechanismus zum Speichern von Daten auf Klassenebene. Felder sind konzeptionell Variablen im Klassenbereich. Wenn Sie einige Daten in Instanzen Ihrer Klassen (Objekte) speichern möchten, müssen Sie Felder verwenden. Es gibt keine andere Wahl. In den Eigenschaften können keine Daten gespeichert werden, obwohl dies anscheinend möglich ist. Siehe unten.
Eigenschaften hingegen speichern niemals Daten. Dies sind nur die Methodenpaare (get und set), die syntaktisch ähnlich wie Felder aufgerufen werden können und auf die in den meisten Fällen zugegriffen wird (zum Lesen oder Schreiben) ) Felder, die einige Verwirrung stiften. Da es sich bei Eigenschaftsmethoden jedoch (mit einigen Einschränkungen wie bei festen Prototypen) um reguläre C # -Methoden handelt, können sie alle regulären Methoden ausführen. Dies bedeutet, dass sie 1000 Codezeilen haben, Ausnahmen auslösen, andere Methoden aufrufen, sogar virtuell, abstrakt oder überschrieben sein können. Das Besondere an Eigenschaften ist, dass der C # -Compiler einige zusätzliche Metadaten in Assemblys speichert, mit denen nach bestimmten Eigenschaften gesucht werden kann - häufig verwendete Funktion.
Die Methode zum Abrufen und Festlegen von Eigenschaften weist die folgenden Prototypen auf.
PROPERTY_TYPE get();
void set(PROPERTY_TYPE value);
Dies bedeutet, dass Eigenschaften 'emuliert' werden können, indem ein Feld und zwei entsprechende Methoden definiert werden.
class PropertyEmulation
{
private string MSomeValue;
public string GetSomeValue()
{
return(MSomeValue);
}
public void SetSomeValue(string value)
{
MSomeValue=value;
}
}
Eine solche Eigenschaftsemulation ist typisch für Programmiersprachen, die keine Eigenschaften unterstützen - wie Standard-C++. In C # sollten Sie immer Eigenschaften bevorzugen, um auf Ihre Felder zugreifen zu können.
Da nur die Felder Daten speichern können, bedeutet dies, dass mehr Felder in der Klasse enthalten sind und mehr Speicherobjekte dieser Klasse belegt werden. Andererseits vergrößert das Hinzufügen neuer Eigenschaften zu einer Klasse Objekte dieser Klasse nicht. Hier ist das Beispiel.
class OneHundredFields
{
public int Field1;
public int Field2;
...
public int Field100;
}
OneHundredFields Instance=new OneHundredFields() // Variable 'Instance' consumes 100*sizeof(int) bytes of memory.
class OneHundredProperties
{
public int Property1
{
get
{
return(1000);
}
set
{
// Empty.
}
}
public int Property2
{
get
{
return(1000);
}
set
{
// Empty.
}
}
...
public int Property100
{
get
{
return(1000);
}
set
{
// Empty.
}
}
}
OneHundredProperties Instance=new OneHundredProperties() // !!!!! Variable 'Instance' consumes 0 bytes of memory. (In fact a some bytes are consumed becasue every object contais some auxiliarity data, but size doesn't depend on number of properties).
Obwohl Eigenschaftsmethoden alles können, dienen sie in den meisten Fällen dazu, auf die Felder von Objekten zuzugreifen. Wenn Sie ein Feld für andere Klassen zugänglich machen möchten, haben Sie zwei Möglichkeiten.
Hier ist eine Klasse, die öffentliche Felder verwendet.
class Name
{
public string FullName;
public int YearOfBirth;
public int Age;
}
Name name=new Name();
name.FullName="Tim Anderson";
name.YearOfBirth=1979;
name.Age=40;
Obwohl der Code vollkommen gültig ist, weist er aus gestalterischer Sicht mehrere Nachteile auf. Da Felder sowohl gelesen als auch geschrieben werden können, können Sie den Benutzer nicht daran hindern, in Felder zu schreiben. Sie können das Schlüsselwort readonly
anwenden. Auf diese Weise müssen Sie jedoch schreibgeschützte Felder nur im Konstruktor initialisieren. Darüber hinaus hindert Sie nichts daran, ungültige Werte in Ihren Feldern zu speichern.
name.FullName=null;
name.YearOfBirth=2200;
name.Age=-140;
Der Code ist gültig, alle Zuweisungen werden ausgeführt, obwohl sie unlogisch sind. Age
hat einen negativen Wert, YearOfBirth
ist weit in der Zukunft und entspricht nicht dem Alter und FullName
ist null. Mit Feldern können Sie Benutzer von class Name
nicht daran hindern, solche Fehler zu machen.
Hier ist ein Code mit Eigenschaften, der diese Probleme behebt.
class Name
{
private string MFullName="";
private int MYearOfBirth;
public string FullName
{
get
{
return(MFullName);
}
set
{
if (value==null)
{
throw(new InvalidOperationException("Error !"));
}
MFullName=value;
}
}
public int YearOfBirth
{
get
{
return(MYearOfBirth);
}
set
{
if (MYearOfBirth<1900 || MYearOfBirth>DateTime.Now.Year)
{
throw(new InvalidOperationException("Error !"));
}
MYearOfBirth=value;
}
}
public int Age
{
get
{
return(DateTime.Now.Year-MYearOfBirth);
}
}
public string FullNameInUppercase
{
get
{
return(MFullName.ToUpper());
}
}
}
Die aktualisierte Version der Klasse bietet die folgenden Vorteile.
FullName
und YearOfBirth
werden auf ungültige Werte überprüft.Age
ist nicht beschreibbar. Es wird aus YearOfBirth
und dem aktuellen Jahr berechnet.FullNameInUppercase
konvertiert FullName
in UPPER CASE. Dies ist ein wenig konstruiertes Beispiel für die Verwendung von Eigenschaften, bei dem Eigenschaften üblicherweise verwendet werden, um Feldwerte in einem Format darzustellen, das für den Benutzer besser geeignet ist - beispielsweise unter Verwendung des aktuellen Gebietsschemas für eine bestimmte Zahl des Formats DateTime
.Daneben können Eigenschaften als virtuell oder überschrieben definiert werden - einfach weil es sich um reguläre .NET-Methoden handelt. Für solche Eigenschaftsmethoden gelten die gleichen Regeln wie für reguläre Methoden.
C # unterstützt auch Indexer, bei denen es sich um Eigenschaften handelt, die in Eigenschaftsmethoden einen Indexparameter aufweisen. Hier ist das Beispiel.
class MyList
{
private string[] MBuffer;
public MyList()
{
MBuffer=new string[100];
}
public string this[int Index]
{
get
{
return(MBuffer[Index]);
}
set
{
MBuffer[Index]=value;
}
}
}
MyList List=new MyList();
List[10]="ABC";
Console.WriteLine(List[10]);
Seit C # 3.0 können Sie automatische Eigenschaften definieren. Hier ist das Beispiel.
class AutoProps
{
public int Value1
{
get;
set;
}
public int Value2
{
get;
set;
}
}
Obwohl class AutoProps
nur Eigenschaften enthält (oder so aussieht), kann es 2 Werte speichern und die Größe von Objekten dieser Klasse entspricht sizeof(Value1)+sizeof(Value2)
= 4 + 4 = 8 Bytes.
Der Grund dafür ist einfach. Wenn Sie eine automatische Eigenschaft definieren, generiert der C # -Compiler automatisch Code, der ein ausgeblendetes Feld und eine Eigenschaft enthält, deren Eigenschaftenmethoden auf dieses ausgeblendete Feld zugreifen. Hier produziert der Code-Compiler.
Hier ist ein Code, der von ILSpy aus einer kompilierten Assembly generiert wird. Klasse enthält generierte ausgeblendete Felder und Eigenschaften.
internal class AutoProps
{
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <Value1>k__BackingField;
[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private int <Value2>k__BackingField;
public int Value1
{
[CompilerGenerated]
get
{
return <Value1>k__BackingField;
}
[CompilerGenerated]
set
{
<Value1>k__BackingField = value;
}
}
public int Value2
{
[CompilerGenerated]
get
{
return <Value2>k__BackingField;
}
[CompilerGenerated]
set
{
<Value2>k__BackingField = value;
}
}
}
Wie Sie sehen, verwendet der Compiler die Felder weiterhin zum Speichern der Werte, da nur mithilfe von Feldern Werte in Objekten gespeichert werden können.
Wie Sie sehen, stellen Eigenschaften und Felder eine ähnliche Verwendungssyntax dar. Auch wenn Sie automatische Eigenschaften oder Ereignisse verwenden, handelt es sich um verborgene Felder Vom Compiler generiert, in dem die realen Daten gespeichert sind.
Wenn Sie einen Feldwert für die Außenwelt zugänglich machen müssen (Benutzer Ihrer Klasse), verwenden Sie keine öffentlichen oder geschützten Felder. Felder sollten immer als privat markiert werden. Mithilfe von Eigenschaften können Sie Wertüberprüfungen, Formatierungen, Konvertierungen usw. durchführen und Ihren Code im Allgemeinen sicherer, lesbarer und erweiterbarer machen, damit er in Zukunft geändert werden kann.
Zusätzliche Informationen: Standardmäßig sind Zugriffsmethoden zum Abrufen und Festlegen so zugänglich wie die Eigenschaft selbst. Sie können den Zugriff auf den Accessor individuell steuern/einschränken (zum Abrufen und Festlegen), indem Sie restriktivere Zugriffsmodifikatoren auf ihn anwenden.
Beispiel:
public string Name
{
get
{
return name;
}
protected set
{
name = value;
}
}
Hier wird immer noch öffentlich auf get zugegriffen (da die Eigenschaft öffentlich ist), aber set ist geschützt (ein eingeschränkterer Zugriffsspezifizierer).