Frage Was ist der Unterschied zwischen einem Feld und einer Eigenschaft?


In C #, was unterscheidet ein Feld von einer Eigenschaft und wann sollte ein Feld anstelle einer Eigenschaft verwendet werden?


826


Ursprung


Antworten:


Eigenschaften legen Felder offen. Felder sollten (fast immer) für eine Klasse privat gehalten werden und über die Eigenschaften get und set aufgerufen werden. Eigenschaften bieten eine Abstraktionsebene, die es Ihnen ermöglicht, die Felder zu ändern, ohne die externe Zugriffsmöglichkeit der Objekte, die Ihre Klasse verwenden, zu beeinflussen.

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 benötigt werden, sie könnten eine Berechnung für andere Felder durchführen oder anderen Zwecken dienen.

@ GSS weist darauf hin, dass Sie auch andere Logik, wie zum Beispiel die Validierung, beim Zugriff auf eine Eigenschaft verwenden können, eine weitere nützliche Funktion.


741



Objektorientierte Programmierungsprinzipien sagen, dass das interne Arbeiten einer Klasse von der Außenwelt verborgen sein sollte. Wenn Sie ein Feld verfügbar machen, stellen Sie im Wesentlichen die interne Implementierung der Klasse offen. Daher umschließen wir Felder mit Eigenschaften (oder Methoden im Fall von Java), um uns die Möglichkeit zu geben, die Implementierung zu ändern, ohne Code zu brechen, abhängig von uns. Da wir die Logik in die Eigenschaft einfügen können, können wir auch eine Validierungslogik usw. ausführen, wenn wir sie brauchen. C # 3 hat die möglicherweise verwirrende Vorstellung von Autoproperties. Dies erlaubt uns, einfach die Eigenschaft zu definieren, und der C # 3-Compiler erzeugt 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
}

207



Ein wichtiger Unterschied besteht darin, dass Schnittstellen Eigenschaften, aber keine Felder haben können. Dies unterstreicht für mich, dass Eigenschaften verwendet werden sollten, um die öffentliche Schnittstelle einer Klasse zu definieren, während Felder dazu bestimmt sind, in den privaten internen Funktionen einer Klasse verwendet zu werden. In der Regel erstelle ich selten öffentliche Felder und auf ähnliche Weise erzeuge ich selten nicht-öffentliche Eigenschaften.


126



Ich gebe Ihnen ein paar Beispiele für die Verwendung von Eigenschaften, die die Zahnräder drehen könnten:

  • Lazy Initialisierung: Wenn Sie eine Eigenschaft eines Objekts haben, das teuer zu laden ist, auf das bei normalen Code-Läufen jedoch nicht viel zugegriffen wird, können Sie das Laden über die Eigenschaft verzögern. Auf diese Weise sitzt es nur dort, aber wenn ein anderes Modul zum ersten Mal versucht, diese Eigenschaft aufzurufen, prüft es, ob das zugrundeliegende Feld null ist - wenn es ist, wird es weiter ausgeführt und lädt es, unbekannt für das aufrufende Modul. Dies kann die Objektinitialisierung erheblich beschleunigen.
  • Schmutziges Tracking: Was ich eigentlich von meinem gelernt habe eigene Frage hier auf StackOverflow. Wenn ich viele Objekte habe, deren Werte sich während eines Laufs geändert haben, kann ich mit der Eigenschaft verfolgen, ob sie in der Datenbank gespeichert werden müssen oder nicht. Wenn sich nicht eine einzelne Eigenschaft eines Objekts geändert hat, wird das IsDirty-Flag nicht ausgelöst, und daher wird die Speicherfunktion es überspringen, wenn entschieden wird, was zurück in die Datenbank gehen soll.

85



Mit den 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 die Stornierung zu unterstützen.

Dies ist mit (direktem Zugriff auf) Feldern 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);
   }
 }
}

43



Da viele von ihnen mit technischen Vor- und Nachteilen erklärt haben Properties und Field, es ist Zeit, in Echtzeit Beispiele zu bekommen.

1. 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 öffentlich für uns. Der Unterschied in der Zugriffsstufe zu ihnen ist, dass wir keinen Wert auf setzen können dataTable.Rows.Count aber wir können lesen und schreiben dataTable.Columns[i].Caption. Ist das möglich durch? Field? Nein!!! Dies kann mit durchgeführt werden Properties nur.

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

Du hättest vielleicht damit gearbeitet Button in Visual Studio. Seine Eigenschaften sind in der PropertyGrid mögen Text,Name usw. Wenn wir eine Schaltfläche ziehen und ablegen und auf die Eigenschaften klicken, wird die Klasse automatisch gefunden Button und Filter Properties und zeigen das in PropertyGrid (woher PropertyGrid wird nicht angezeigt 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;
        }
   } 

Im PropertyGrid, die Eigenschaften Name und Text wird angezeigt, aber nicht SomeProperty. Warum??? Weil Eigenschaften akzeptieren können Attribute. Es zeigt nicht, wenn [Browsable(false)] ist falsch.

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 der Bindungsquelle können nur Eigenschaften verwendet werden

Bindequelle hilft uns, die Anzahl der Codezeilen zu verringern. Fields werden nicht akzeptiert von BindingSource. Wir sollten ... benutzen Properties dafür.

5. Debugging-Modus

Überlegen Sie, wir verwenden Field einen Wert halten. Irgendwann müssen wir debuggen und überprüfen, wo der Wert für dieses Feld null wird. Es wird schwierig sein, zu tun, wo die Anzahl der Codezeilen mehr als 1000 ist. In solchen Situationen können wir verwenden Property und kann den Debug-Modus einstellen Property.

   public string Name
   {
        // Can set debug mode inside get or set
        get
        {
           return _name;
        }
        set
        {
           _name = value;
        }
   }

36



UNTERSCHIEDE - VERWENDUNGEN (wann und warum)

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 haben. Im Allgemeinen sollten Sie Felder verwenden nur für Variablen mit privater oder geschützter Verfügbarkeit. Daten, die Ihre Klasse dem Client-Code zur Verfügung stellt sollte durch Methoden, Eigenschaften zur Verfügung gestellt werden und Indexer. Wenn Sie diese Konstrukte für den indirekten Zugriff auf interne Felder verwenden, können Sie sich vor ungültigen Eingabewerten schützen.

EIN Eigentum ist ein Element, das 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, aber sie sind tatsächlich spezielle aufgerufene Methoden Accessoren. Dies ermöglicht den einfachen Zugriff auf Daten und trägt weiterhin zur Förderung des Sicherheit und Flexibilität der Methoden. Eigenschaften ermöglichen es einer Klasse, eine öffentliche Methode zum Abrufen und Festlegen von Werten verfügbar zu machen, während der Implementierungs- oder Verifizierungscode ausgeblendet wird. Ein Get-Eigenschaft-Accessor wird verwendet, um den Eigenschaftswert zurückzugeben, und ein Set-Accessor wird verwendet, um einen neuen Wert zuzuweisen.


21



Eigenschaften haben den Hauptvorteil, dass Sie die Art ändern können, in der auf Daten auf einem Objekt zugegriffen wird, ohne die öffentliche Schnittstelle zu unterbrechen. Wenn Sie beispielsweise eine zusätzliche Überprüfung hinzufügen oder ein gespeichertes Feld in ein berechnetes Feld ändern möchten, können Sie dies leicht tun, wenn Sie das Feld zunächst als Eigenschaft angezeigt haben. Wenn Sie ein Feld direkt angezeigt haben, müssten Sie die öffentliche Schnittstelle Ihrer Klasse ändern, um die neue Funktionalität hinzuzufügen. Durch diese Änderung werden vorhandene Clients aufgelöst und müssen neu kompiliert werden, bevor sie die neue Version Ihres Codes verwenden können.

Wenn Sie eine Klassenbibliothek schreiben, die für eine breite Verwendung konzipiert ist (wie das .NET Framework, das von Millionen von Benutzern verwendet wird), kann das ein Problem sein. Wenn Sie jedoch eine Klasse schreiben, die intern in einer kleinen Codebasis verwendet wird (sagen wir <= 50 K-Zeilen), ist das wirklich keine große Sache, weil niemand von Ihren Änderungen beeinträchtigt wird. In diesem Fall kommt es wirklich nur auf persönliche Vorlieben an.


9



Eigenschaften unterstützen den asymmetrischen Zugriff, d.h. Sie können entweder einen Getter und einen Setter oder nur einen der beiden haben. Ähnlich Eigenschaften unterstützen individuelle Zugänglichkeit für Getter / Setter. Felder sind immer symmetrisch, d. H. Sie können den Wert immer abrufen und festlegen. Ausgenommen davon sind schreibgeschützte Felder, die offensichtlich nach der Initialisierung nicht gesetzt werden können.

Eigenschaften können sehr lange laufen, 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 es bei DateTime.Now der Fall ist, 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 nicht. Eigenschaften unterstützen zusätzliche Logik - dies könnte unter anderem zur Implementierung von Lazy Loading verwendet werden.

Eigenschaften unterstützen eine Abstraktionsebene, indem sie alles einkapseln, was es bedeutet, den Wert zu erhalten / setzen.

Verwenden Sie Eigenschaften in den meisten / allen Fällen, aber versuchen Sie, Nebenwirkungen zu vermeiden.


7



Im Hintergrund wird eine Eigenschaft in Methoden kompiliert. Also a Name Eigenschaft wird in kompiliert get_Name() und set_Name(string value). Sie können dies sehen, wenn Sie den kompilierten Code studieren. Es gibt also einen (sehr) geringen Leistungsaufwand bei der Verwendung. Normalerweise werden Sie immer eine Eigenschaft verwenden, wenn Sie ein Feld nach außen freigeben, und Sie werden es oft intern verwenden, wenn Sie den Wert validieren müssen.


7