Was unterscheidet in C# ein Feld von einer Eigenschaft, und wann sollte ein Feld anstelle einer Eigenschaft verwendet werden?
Antworten
Zu viele Anzeigen?Eigenschaften legen Felder frei. Felder sollten (fast immer) privat für eine Klasse gehalten werden und über get- und set-Eigenschaften zugänglich sein. Eigenschaften bieten eine Abstraktionsebene, die es Ihnen ermöglicht, die Felder zu ändern, ohne die Art und Weise zu beeinflussen, in der von außen auf sie zugegriffen wird, wenn Ihre Klasse verwendet wird.
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 keine Felder kapseln müssen, sondern auch andere Felder berechnen oder anderen Zwecken dienen können.
@GSS weist darauf hin, dass beim Zugriff auf eine Eigenschaft auch eine andere Logik, z. B. eine Validierung, durchgeführt werden kann, eine weitere nützliche Funktion.
Die Grundsätze der objektorientierten Programmierung besagen, dass die interne Funktionsweise einer Klasse vor der Außenwelt verborgen bleiben sollte. Wenn Sie ein Feld offenlegen, legen Sie im Wesentlichen die interne Implementierung der Klasse offen. Deshalb umhüllen wir Felder mit Eigenschaften (oder Methoden in Javas Fall), um uns die Möglichkeit zu geben, die Implementierung zu ändern, ohne den von uns abhängigen Code zu zerstören. Da wir Logik in die Eigenschaft einbauen können, können wir bei Bedarf auch eine Validierungslogik usw. durchführen. C# 3 hat den möglicherweise verwirrenden Begriff der Autoproperties. Damit können wir einfach die Eigenschaft definieren und der C#3-Compiler wird das private Feld für uns generieren.
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 ist, dass Schnittstellen Eigenschaften haben können, aber keine Felder. Dies unterstreicht meiner Meinung nach, dass Eigenschaften dazu verwendet werden sollten, die öffentliche Schnittstelle einer Klasse zu definieren, während Felder für die privaten, internen Abläufe einer Klasse gedacht sind. In der Regel erstelle ich nur selten öffentliche Felder, und ebenso selten erstelle ich nicht-öffentliche Eigenschaften.
Ich gebe Ihnen ein paar Beispiele für die Verwendung von Eigenschaften, die Sie zum Nachdenken anregen könnten:
- Faule Initialisierung : Wenn Sie eine Eigenschaft eines Objekts haben, deren Laden teuer ist, auf die aber bei normalen Codeausführungen nicht so oft zugegriffen wird, können Sie das Laden über die Eigenschaft verzögern. Auf diese Weise wird die Eigenschaft nicht geladen, aber wenn ein anderes Modul zum ersten Mal versucht, die Eigenschaft aufzurufen, wird geprüft, ob das zugrunde liegende Feld null ist. Ist dies der Fall, wird die Eigenschaft geladen, ohne dass das aufrufende Modul davon weiß. Dies kann die Objektinitialisierung erheblich beschleunigen.
- Schmutziges Tracking: Das habe ich eigentlich von meinem eigene Frage hier auf StackOverflow. Wenn ich viele Objekte habe, deren Werte sich während eines Laufs geändert haben könnten, kann ich die Eigenschaft verwenden, um zu verfolgen, ob sie in die Datenbank zurückgespeichert werden müssen oder nicht. Wenn sich keine einzige Eigenschaft eines Objekts geändert hat, wird das IsDirty-Flag nicht ausgelöst und die Speicherfunktion überspringt es bei der Entscheidung, was in die Datenbank zurückgespeichert werden muss.
Bei der Verwendung von Eigenschaften können Sie ein Ereignis auslösen, wenn der Wert der Eigenschaft geändert wird (auch bekannt als PropertyChangedEvent) oder bevor der Wert geändert wird, um einen Abbruch 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(){
NameChanging?.Invoke(this,EventArgs.Empty);
}
private void OnNameChanged(){
NameChanged?.Invoke(this,EventArgs.Empty);
}
}
- See previous answers
- Weitere Antworten anzeigen