Was ist der Unterschied zwischen einem Feld und einer Eigenschaft?

1130

Was unterscheidet ein Feld in C # von einer Eigenschaft und wann sollte ein Feld anstelle einer Eigenschaft verwendet werden?

anonym
quelle
32
Microsoft beantwortet diese Frage (für alle .NET-Sprachen) direkt im Rahmen seiner Richtlinien für das Design von Mitgliedern . Einzelheiten finden Sie in den Artikeln Property Design und Field Design . Beachten Sie, dass zwischen Instanzmitgliedern und statischen Mitgliedern unterschieden wird.
DavidRR

Antworten:

979

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 die externe Art und Weise zu beeinflussen, auf die die Benutzer Ihrer Klasse 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, sondern eine Berechnung für andere Felder durchführen oder anderen Zwecken dienen können.

@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.

Cory
quelle
185
Es ist erwähnenswert, dass Eigenschaften nicht erforderlich sind, um Felder zu kapseln. Es konnte überhaupt kein Feld hinter dem Grundstück sein. Es könnte eine Berechnung sein oder eine Konstante oder was auch immer zurückgeben.
Kent Boogaart
9
"Ohne die externe Art und Weise zu beeinflussen, auf die die Dinge zugreifen, die Ihre Klasse verwenden." Verzeihen Sie mir, wenn ich das falsch verstehe, aber warum müssen überhaupt Zugriffsmodifikatoren vor den Eigenschaften benötigt werden, wenn das Feld dahinter dies zu handhaben scheint? dh warum eine Immobilie etwas anderes als öffentlich machen?
Chucky
18
Ihre Antwort war direkt vor den Änderungen und seltsamerweise hoch bewerteten falschen Kommentaren. Eine Eigenschaft sollte immer ein oder mehrere Felder einkapseln und niemals schweres Heben oder Validieren durchführen. Wenn Sie für die Validierung eine Eigenschaft wie Benutzername oder Kennwort benötigen, ändern Sie deren Typ von Zeichenfolgen in Wertobjekte . Es besteht ein unausgesprochener Vertrag zwischen einem Klassenschöpfer und dem Verbraucher. Felder halten den Status, Eigenschaften legen den Status mithilfe eines oder mehrerer Felder offen, Hohlräume ändern den Status (schweres Heben) und Funktionen führen Abfragen aus (schweres Heben). Dies ist kein Stein, sondern nur lose Erwartungen.
Suamere
6
@jpaugh Wenn ich ein Klassenkonsument bin, folge ich den vom Klassenersteller festgelegten Verträgen. Wenn es sich um eine Immobilie handelt string, lautet mein Vertrag: Weisen Sie Zeichen mit einer Länge von bis zu ~ 2bil zu. Wenn es sich um eine Immobilie handelt DateTime, lautet mein Vertrag: Weisen Sie innerhalb der Grenzen von DateTime beliebige Nummern zu, die ich nachschlagen kann. Wenn der Ersteller den Setzern Einschränkungen hinzufügt, werden diese Einschränkungen nicht kommuniziert. Wenn der Ersteller stattdessen den Typ von stringin ändert Surname, kommuniziert die neue Nachnamenklasse die Einschränkungen, und die Eigenschaft public Surname LastNameverfügt nicht über eine Setter-Validierung. Ist auch Surnamewiederverwendbar.
Suamere
4
Und da es Surnamein meinem Beispiel wiederverwendbar ist, müssen Sie sich später keine Gedanken mehr darüber machen, wie Sie diese Überprüfungen in einem Eigenschaftssetter an andere Stellen im Code kopieren / einfügen. Sie fragen sich auch nicht, ob die Validierung eines Nachnamens an mehreren Stellen erfolgt, wenn Sie jemals Änderungen an den Geschäftsregeln für Nachnamen vornehmen. Schauen Sie sich den Link an, den ich über Value Objects
Suamere
261

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), um die Implementierung zu ändern, ohne den Code abhängig von uns zu beschädigen. Da wir Logik in die Eigenschaft einfügen können, können wir auch Validierungslogik usw. ausführen, wenn wir sie benötigen. C # 3 hat die möglicherweise verwirrende Vorstellung von Autoproperties. Auf diese Weise 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
}
danswain
quelle
89
+1 für die Erwähnung von Autoproperties - Ich denke, dies ist etwas, was viele der Antworten hier (und anderswo) vergessen haben einzubringen. Ohne diese Erklärung kann es immer noch ziemlich schwer sein zu verstehen, wofür es public int myVar { get; set; }wirklich steht (und ich nehme an, dass es der Grund ist für mindestens 50% der Treffer erhält diese Frage).
Priidu Neemre
7
+1 auch für die Erwähnung von Auto und die Funktionsweise ("AutoProperty generiert ein privates Feld für uns") Dies war die Antwort, nach der ich auf eine Frage gesucht habe, die ich hatte. Bei der Recherche habe ich auf der MSDN-Seite keinen Hinweis darauf gesehen, dass ein privates Feld erstellt wurde und Verwirrung stiftete. Ich denke das ist was das bedeutet? "Attribute sind für automatisch implementierte Eigenschaften zulässig, aber offensichtlich nicht für die Sicherungsfelder, da auf diese über Ihren Quellcode nicht zugegriffen werden kann. Wenn Sie ein Attribut für das Sicherungsfeld einer Eigenschaft verwenden müssen, erstellen Sie einfach eine reguläre Eigenschaft." war mir aber nicht sicher.
Nyra
3
Beachten Sie, dass das angegebene Beispiel keine Kniebeugen enthält. Diese Eigenschaft bietet 100% vollständigen Zugriff auf das private Feld, sodass dies überhaupt nicht objektorientiert ist. In diesem Fall können Sie auch ein öffentliches Feld haben. Zugegeben, es hilft (geringfügig), Code in Zukunft umzugestalten, aber jede IDE, die es wert ist, kann ein Feld mit wenigen Tastenanschlägen in eine Eigenschaft umwandeln. Die Antwort mag technisch korrekt sein, was die Funktionsweise von Eigenschaften betrifft, gibt jedoch keine gute "OOP-Erklärung" für ihre Verwendung.
Sara
2
@kai Ich stimme zu, dass die Antwort die Dinge zu stark vereinfacht und nicht die ganze Kraft einer Auto-Eigenschaft zeigt, aber ich bin nicht der Meinung, dass dies nicht objektorientiert ist. Möglicherweise möchten Sie den Unterschied zwischen Feldern und Eigenschaften überprüfen . Felder können nicht virtuell sein und sind virtualselbst Teil der objektorientierten Programmierung.
Gobe
Zugegeben, es gibt einige funktionale Unterschiede. Ich würde virtualOOP jedoch nicht per se anrufen . Es ist ein Werkzeug, das Polymorphismus ermöglicht. Dies ist eines der Schlüsselwerkzeuge, die OOP AKTIVIEREN. Es ist jedoch nicht OOP an und für sich, und an einer öffentlichen Autoproperty ist nichts von Natur aus OOP. Ich würde auch Dinge wie Reflection oder OOP im Zusammenhang mit der Datenbindung nicht zählen. Normalerweise wäre ich nicht so pedantisch, aber in der Antwort wurden speziell die OO-Prinzipien als treibende Kraft hinter dem Codebeispiel genannt, und dem stimme ich nicht zu.
Sara
164

Ein wichtiger Unterschied besteht darin, dass Schnittstellen Eigenschaften haben können, jedoch 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 privaten, internen Abläufe einer Klasse verwendet werden sollen. In der Regel erstelle ich selten öffentliche Felder und in ähnlicher Weise auch nicht öffentliche Eigenschaften.

Hans Løken
quelle
98

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

  • Lazy Initialization : Wenn Sie eine Eigenschaft eines Objekts haben, deren Laden teuer ist, auf die in normalen Codeläufen jedoch nicht so häufig 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 zugrunde liegende Feld null ist. Wenn dies der Fall ist, wird es geladen und dem aufrufenden Modul unbekannt. Dies kann die Objektinitialisierung erheblich beschleunigen.
  • Dirty Tracking: Was ich aus meiner eigenen Frage hier bei StackOverflow gelernt habe . Wenn ich viele Objekte habe, deren Werte sich während eines Laufs möglicherweise geändert haben, kann ich mithilfe der Eigenschaft verfolgen, ob sie wieder in der Datenbank gespeichert werden müssen oder nicht. Wenn sich keine einzelne Eigenschaft eines Objekts geändert hat, wird das IsDirty-Flag nicht ausgelöst, und daher wird die Speicherfunktion bei der Entscheidung, was zur Datenbank zurückkehren soll, übersprungen.
Chris
quelle
1
Eine Frage zu Dirty Tracking: Was wäre, wenn ich das Feld direkt ändern könnte? Ich weiß nicht, ob dies möglich ist. Ich könnte sagen: "Das Objekt muss nicht gespeichert werden, wenn sich nicht ein einzelnes FELD eines Objekts geändert hat." Dirty Tracking wäre also kein Unterschied. Vermisse ich etwas?
Websites
2
@juanpastas: Der Vorteil von Eigenschaften in Bezug auf Dirty Tracking besteht darin, dass in dem Szenario, in dem das Flag nicht gesetzt ist, der Code die Werte von Eigenschaften nicht überprüfen muss, um zu sehen, ob Eigenschaftssetzer ein "Dirty" -Flag setzen wenn sie sich geändert haben könnten. Wenn ein Objekt dagegen seine Attribute als Felder verfügbar macht, muss der Inhalt aller Felder mit dem vorherigen Wert verglichen werden (was nicht nur die Zeit für den Vergleich erhöht, sondern auch bedeutet, dass der Code den vorherigen Wert haben muss ).
Supercat
Dies ist eine gute Möglichkeit. Sie können auch Methoden (als Ereignisse) auslösen oder protokollieren, wenn der Wert festgelegt oder gelesen wird.
Coloboxp
54

Mit 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(){       
     NameChanging?.Invoke(this,EventArgs.Empty);       
 }

 private void OnNameChanged(){
     NameChanged?.Invoke(this,EventArgs.Empty);
 }
}
Jehof
quelle
3
Ich habe lange gebraucht, um das zu finden. Dies ist eine MVVM . Vielen Dank ! :)
46

Da viele von ihnen mit technischen Vor- und Nachteilen von Propertiesund erklärt haben Field, ist es Zeit, sich mit Beispielen in Echtzeit zu befassen.

1. Mit Eigenschaften können Sie die schreibgeschützte Zugriffsebene festlegen

Betrachten Sie den Fall von dataTable.Rows.Countund dataTable.Columns[i].Caption. Sie kommen aus der Klasse DataTableund beide sind für uns öffentlich. Der Unterschied in der Zugriffsebene besteht darin, dass wir keinen Wert festlegen können, dataTable.Rows.Countaber lesen und schreiben können dataTable.Columns[i].Caption. Ist das möglich durch Field? Nein!!! Dies ist nur mit möglich Properties.

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 Buttonin Visual Studio mit gearbeitet. Seine Eigenschaften sind in der gezeigt PropertyGridwie Text, Nameusw. Wenn wir ziehen und einen Knopf fallen, und wenn wir die Eigenschaften klicken, wird es automatisch die Klasse finden Buttonund Filter Propertiesund zeigen , dass in PropertyGrid(wo PropertyGridzeigen nicht , Fieldauch wenn 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 PropertyGridwerden die Eigenschaften Nameund Textangezeigt, aber nicht SomeProperty. Warum??? Weil Eigenschaften Attribute akzeptieren können . Es wird nicht angezeigt, wenn [Browsable(false)]es falsch ist.

3. Kann Anweisungen in Eigenschaften 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

Mit Binding Source können wir die Anzahl der Codezeilen verringern. Fieldswerden von nicht akzeptiert BindingSource. Wir sollten dafür verwenden Properties.

5. Debugging-Modus

Stellen Sie sich vor, wir verwenden Field, um einen Wert zu halten. Irgendwann müssen wir debuggen und überprüfen, wo der Wert für dieses Feld null wird. Es wird schwierig sein, wenn die Anzahl der Codezeilen mehr als 1000 beträgt. In solchen Situationen können wir Propertyden Debug-Modus verwenden und festlegen Property.

   public string Name
   {
        // Can set debug mode inside get or set
        get
        {
           return _name;
        }
        set
        {
           _name = value;
        }
   }
Sarath Avanavu
quelle
Dies sind interessante Fakten, aber Sie vermissen den Punkt der Feld- und Eigenschaftenphilosophie.
David Ferenczy Rogožan
Was meinst du mit PHILISOPHIE ? @ Dawid Ferenczy
Sarath Avanavu
Siehe zum Beispiel markierte Antwort. Aber Sie haben bemerkt, dass Sie nur ein Verwendungsbeispiel angeben, da der Unterschied zwischen Feldern und Eigenschaften bereits beschrieben wurde. Vergessen Sie daher bitte meinen Kommentar :)
David Ferenczy Rogožan
2
Lesen Sie meinen ersten Satz in meiner Antwort. Ich habe ausdrücklich gesagt, dass ich hier nicht alles noch einmal wiederholen werde. Das macht keinen Sinn!!! Die Leute werden zuerst die Beschreibung und dann die Beispiele betrachten. Die markierte Antwort gibt die Beschreibung gut wieder, aber ich habe einige Echtzeitszenarien und Beispiele hinzugefügt, die sinnvoll sind. Bitte stellen Sie sicher, dass Sie aus der Sicht des Lesers denken, bevor Sie @Dawid Ferenczy
Sarath Avanavu
1
Ich habe es gelesen, aber Sie haben meinen vorherigen Kommentar offensichtlich nicht gelesen: " Aber Sie haben bemerkt, dass Sie nur Verwendungsbeispiele bereitstellen, da der Unterschied zwischen Feldern und Eigenschaften bereits beschrieben wurde. Vergessen Sie also bitte meinen Kommentar :) " .
David Ferenczy Rogožan
32

UNTERSCHIEDE - VERWENDUNG (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 nur für Variablen verwenden, die einen privaten oder geschützten Zugriff haben . Daten, die Ihre Klasse für Clientcode verfügbar macht, sollten über Methoden, Eigenschaften und Indexer bereitgestellt werden. Durch die Verwendung dieser Konstrukte für den indirekten Zugriff auf interne Felder können Sie sich vor ungültigen Eingabewerten schützen.

Eine Eigenschaft ist ein Mitglied, das einen flexiblen Mechanismus zum Lesen, Schreiben oder Berechnen des Werts eines privaten Felds bietet. Eigenschaften können so verwendet werden, als wären sie öffentliche Datenelemente, aber es handelt sich tatsächlich um spezielle Methoden, die als Accessoren bezeichnet werden . Dies ermöglicht den einfachen Zugriff auf Daten und fördert dennoch die Sicherheit und Flexibilität der Methoden . Mithilfe von Eigenschaften kann eine Klasse eine öffentliche Methode zum Abrufen und Festlegen von Werten verfügbar machen, während Implementierungs- oder Überprüfungscode ausgeblendet wird. Ein get-Eigenschafts-Accessor wird verwendet, um den Eigenschaftswert zurückzugeben, und ein festgelegter Accessor wird verwendet, um einen neuen Wert zuzuweisen.

makiSTB
quelle
Dies ist eine großartige Antwort, die mir wirklich geholfen hat, dies zu verstehen.
Steve Bauman
14

Eigenschaften haben den Hauptvorteil, dass Sie die Art und Weise ändern können, in der auf Daten eines Objekts zugegriffen wird, 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 nur ein Feld direkt verfügbar gemacht haben, müssen 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 erfordern, bevor sie die neue Version Ihres Codes verwenden können.

Wenn Sie eine Klassenbibliothek schreiben, die für einen 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 verwendet wird (z. B. <= 50 K Zeilen), ist dies keine große Sache, da niemand durch Ihre Änderungen beeinträchtigt würde. In diesem Fall kommt es wirklich nur auf die persönlichen Vorlieben an.

Scott Wisniewski
quelle
11

Die Eigenschaften unterstützen den asymmetrischen Zugriff, dh Sie können entweder einen Getter und einen Setter oder nur einen der beiden haben. In ähnlicher Weise unterstützen Eigenschaften die individuelle Zugänglichkeit für Getter / Setter. Felder sind immer symmetrisch, dh Sie können den Wert immer sowohl abrufen als auch einstellen. Eine Ausnahme bilden schreibgeschützte Felder, die nach der Initialisierung offensichtlich 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 dies bei DateTime.Now der Fall sein kann, dh 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 könnte unter anderem verwendet werden, um ein verzögertes Laden zu implementieren.

Eigenschaften unterstützen eine Abstraktionsebene, indem sie kapseln, was auch immer es bedeutet, den Wert abzurufen / festzulegen.

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

Brian Rasmussen
quelle
Felder können alle Kostenprobleme von Eigenschaften aufweisen, wenn der Datentyp des Felds ein Objekt mit einer Überladung des Konvertierungsoperators ist - es ist ein subtiles Problem.
Andy Dent
1
Eigenschaften sollten niemals Nebenwirkungen haben. Sogar der Debugger geht davon aus, dass er sie sicher auswerten kann.
Craig Gidney
@Strilanc: Ich stimme vollkommen zu, das ist jedoch nicht immer der Fall. Was den Debugger betrifft, gibt es viele Probleme mit FuncEval, wenn Sie darüber sprechen.
Brian Rasmussen
11

Im Hintergrund wird eine Eigenschaft in Methoden kompiliert. So wird eine NameEigenschaft in get_Name()und kompiliert set_Name(string value). Sie können dies sehen, wenn Sie den kompilierten Code studieren. Daher entsteht bei der Verwendung ein (sehr) geringer Leistungsaufwand. Normalerweise verwenden Sie immer eine Eigenschaft, wenn Sie ein Feld nach außen offenlegen, und Sie verwenden sie häufig intern, wenn Sie eine Validierung des Werts durchführen müssen.

Rune Grimstad
quelle
7

Wenn Sie möchten, dass Ihre private Variable (Feld) für Objekte Ihrer Klasse aus anderen Klassen zugänglich ist, müssen Sie Eigenschaften für diese Variablen erstellen.

Zum Beispiel, wenn ich Variablen mit den Namen "id" und "name" habe, die privat sind, aber es kann vorkommen, dass diese Variable für Lese- / Schreibvorgänge außerhalb der Klasse benötigt wird. In dieser Situation kann mir die Eigenschaft helfen, diese Variable in Abhängigkeit von der für die Eigenschaft definierten get / set zum Lesen / Schreiben zu bringen. Eine Eigenschaft kann sowohl schreibgeschützt als auch 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";
    }
}
Petryanu
quelle
6

Die zweite Frage hier, "wann sollte ein Feld anstelle einer Eigenschaft verwendet werden?", Wird in dieser anderen Antwort nur kurz angesprochen und irgendwie auch in dieser , aber nicht wirklich detailliert.

Im Allgemeinen sind alle anderen Antworten genau richtig für gutes Design: Belichten Sie lieber Eigenschaften als Felder. Während Sie wahrscheinlich nicht regelmäßig sagen werden: "Wow, stellen Sie sich vor, wie viel schlimmer es wäre, wenn ich dies zu einem Feld anstelle eines Grundstücks gemacht hätte", ist es so viel seltener, an eine Situation zu denken, in der Sie "Wow," sagen würden. Gott sei Dank habe ich 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 wie folgt erstelltes Array zu transformieren:

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 geht:

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);
}

Wenn Sie einige Messungen selbst durchführen, nimmt die Version mit Feldern etwa 61% der Zeit in Anspruch, da die Version mit Eigenschaften (.NET 4.6, Windows 7, x64, Release-Modus, kein Debugger angeschlossen). Je teurer die TransformPointMethode wird, desto weniger ausgeprägt wird der Unterschied. Um dies selbst zu wiederholen, führen Sie die erste Zeile auskommentiert und die nicht auskommentiert 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 der Methodenfamilie Interlocked oder Volatile . Hinweis: Falls dies für Sie neu ist, ist Volatile im Grunde eine Möglichkeit, das gleiche Verhalten wie das volatileSchlüsselwort zu erreichen. Als solches volatilelöst es nicht auf magische Weise alle Probleme mit der Thread-Sicherheit, wie der Name vermuten lässt.

Ich möchte definitiv nicht so aussehen, als würde ich befürworten, dass Sie sagen: "Oh, ich sollte anfangen, Felder anstelle von Eigenschaften freizulegen." Der Punkt ist, dass, wenn Sie diese Elemente regelmäßig in Aufrufen verwenden müssen, die "ref" - oder "out" -Parameter verwenden, insbesondere für einen einfachen Werttyp, für den wahrscheinlich nie eines der Mehrwertelemente von Eigenschaften erforderlich ist. es kann ein Argument vorgebracht werden.

Joe Amenta
quelle
6

Obwohl Felder und Eigenschaften einander ähnlich zu sein scheinen, sind sie zwei völlig unterschiedliche Sprachelemente.

  1. 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. Eigenschaften können keine Daten speichern, obwohl sie möglicherweise dazu in der Lage sind. Siehe unten.

  2. Eigenschaften hingegen speichern niemals Daten. Sie sind nur die Methodenpaare (get und set), die auf ähnliche Weise wie Felder syntaktisch aufgerufen werden können, und in den meisten Fällen greifen sie auf (zum Lesen oder Schreiben) Felder zu, was zu Verwirrung führt. Da Eigenschaftsmethoden jedoch (mit einigen Einschränkungen wie dem festen Prototyp) reguläre C # -Methoden sind, können sie alle regulären Methoden ausführen. Dies bedeutet, dass sie 1000 Codezeilen haben können, Ausnahmen auslösen, andere Methoden aufrufen, sogar virtuell, abstrakt oder überschrieben sein können. Das Besondere an Eigenschaften ist die Tatsache, dass der C # -Compiler einige zusätzliche Metadaten in Assemblys speichert, mit denen nach bestimmten Eigenschaften gesucht werden kann - eine weit verbreitete Funktion.

Das Abrufen und Festlegen von Eigenschaftsmethoden umfasst die folgenden Prototypen.

PROPERTY_TYPE get();

void set(PROPERTY_TYPE value);

Dies bedeutet, dass Eigenschaften durch Definieren eines Felds und zweier entsprechender Methoden "emuliert" werden können.

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 Feldklassen enthalten und mehr Speicherobjekte dieser Klasse verbraucht werden. Wenn Sie jedoch einer Klasse neue Eigenschaften hinzufügen, werden Objekte dieser Klasse nicht größer. 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 als Möglichkeit, auf die Felder von Objekten zuzugreifen. Wenn Sie ein Feld für andere Klassen zugänglich machen möchten, haben Sie zwei Möglichkeiten.

  1. Felder öffentlich machen - nicht ratsam.
  2. Eigenschaften verwenden.

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 aus gestalterischer Sicht vollkommen gültig ist, weist er 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 ein readonlySchlüsselwort anwenden , aber auf diese Weise müssen Sie 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. Agehat einen negativen Wert, YearOfBirthist weit in der Zukunft und entspricht nicht dem Alter und FullNameist null. Mit Feldern können Sie Benutzer nicht daran hindern class Name, 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.

  1. FullNameund YearOfBirthwerden auf ungültige Werte überprüft.
  2. Ageist nicht schreibbar. Es ist ab dem YearOfBirthlaufenden Jahr aufgerufen .
  3. Eine neue Eigenschaft FullNameInUppercasewird FullNamein UPPER CASE konvertiert . Dies ist ein wenig erfundenes Beispiel für die Verwendung von Eigenschaften, bei dem Eigenschaften häufig verwendet werden, um Feldwerte in dem Format darzustellen, das für den Benutzer besser geeignet ist - beispielsweise unter Verwendung des aktuellen Gebietsschemas für eine bestimmte Formatnummer DateTime.

Darüber hinaus können Eigenschaften als virtuell oder überschrieben definiert werden - einfach weil es sich um reguläre .NET-Methoden handelt. Für solche Eigenschaftsmethoden gelten dieselben Regeln wie für reguläre Methoden.

C # unterstützt auch Indexer, bei denen es sich um Eigenschaften handelt, die in Eigenschaftsmethoden einen Indexparameter haben. 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 es class AutoPropsnur 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 automatischen Code, der ein verstecktes Feld und eine Eigenschaft mit Eigenschaftsmethoden enthält, die auf dieses versteckte Feld zugreifen. Hier wird der Code-Compiler erstellt.

Hier ist ein Code, der von ILSpy aus einer kompilierten Assembly generiert wird . Klasse enthält generierte versteckte 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 Felder die einzige Möglichkeit sind, Werte in Objekten zu speichern.

Wie Sie sehen können, sind Eigenschaften und Felder zwar eine ähnliche Verwendungssyntax, aber sehr unterschiedliche Konzepte. Selbst wenn Sie automatische Eigenschaften oder Ereignisse verwenden - versteckte Felder werden vom Compiler generiert, in dem die realen Daten gespeichert werden.

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. Mit den Eigenschaften können Sie Wertprüfungen, Formatierungen, Konvertierungen usw. durchführen und Ihren Code im Allgemeinen sicherer, lesbarer und erweiterbarer für zukünftige Änderungen machen.

Timmy_A
quelle
4

Mit Eigenschaften können Sie auch Logik beim Festlegen von Werten verwenden.

Sie können also sagen, dass Sie einen Wert nur dann auf ein Ganzzahlfeld setzen möchten, wenn der Wert größer als x ist. Andernfalls wird eine Ausnahme ausgelöst.

Wirklich nützliche Funktion.

GurdeepS
quelle
4

Wenn Sie Thread-Grundelemente verwenden möchten, müssen Sie Felder verwenden. Eigenschaften können Ihren Thread-Code beschädigen. Abgesehen davon ist das, was Cory gesagt hat, richtig.

Jonathan C Dickinson
quelle
1
seit wann? Sperren Sie Ihr Hintergrundfeld innerhalb des Grundstücks und es ist das Äquivalenz
Sekhat
1
Eigenschaften sind Methoden und werden heute von keinem CIL JIT inliniert. Wenn Sie Thread-Grundelemente wie Interlocked verwenden möchten, benötigen Sie Felder. Überprüfen Sie Ihre Quellen. Zugegebenermaßen war "Sperren" das falsche Wort.
Jonathan C Dickinson
4

(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 empfohlen wurde, ö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 bei Bedarf später in eine Immobilie umgewandelt werden könnte. Es kam mir damals etwas seltsam vor. Nach diesen Beiträgen zu urteilen, scheinen auch nicht viele hier zuzustimmen. Was könnten Sie gesagt haben, um zu versuchen, Dinge zu ändern?

Bearbeiten: Ich sollte hinzufügen, dass die gesamte Codebasis an dieser Stelle zur gleichen Zeit kompiliert wurde, sodass sie möglicherweise gedacht haben, dass das Ändern der öffentlichen Schnittstelle von Klassen (durch Ändern eines öffentlichen Felds in eine Eigenschaft) kein Problem darstellt.

Moe Sisko
quelle
Seit C # 3.0 wird das hier beschriebene Muster bequem von einer Funktion namens Auto-Implemented Properties unterstützt .
DavidRR
Ich denke, einer der Vorteile von C # mit Eigenschaften, da sie dieselbe API wie Felder haben, sodass es Clients der Klasse egal ist, ob sie auf eine Eigenschaft oder ein Feld zugreifen. (Dies gilt beispielsweise NICHT für C ++). Beim Prototyping halte ich es für sinnvoll, mit öffentlichen Feldern zu beginnen und dann nach Bedarf zu Eigenschaften zu migrieren. Es gibt einen Leistungs- und Speicher-Hit mit Eigenschaften, und es gibt zusätzliche Eingabe. Sie sind nicht frei. Wenn Sie jedoch Ihre Meinung ändern, müssen Sie keinen abhängigen Code umgestalten.
Mark Lakata
Eigenschaften können nicht als OUT- oder REF-Parameter verwendet werden. Das Ändern eines Felds in eine Eigenschaft kann daher zu Kompilierungsfehlern führen. Wenn der Wert von Anfang an als Eigenschaft implementiert worden wäre, wäre er niemals als OUT- oder REF-Parameter (VAR in Pascal / Delphi) verwendet worden, und jede Änderung, die Sie am Getter / Setter vornehmen, wäre für die Verwendung transparent.
HeartWare
4

Technisch gesehen glaube ich nicht, dass es einen Unterschied gibt, da Eigenschaften nur Wrapper um Felder sind, die vom Benutzer erstellt oder automatisch vom Compiler erstellt wurden. Der Zweck von Eigenschaften besteht darin, die Kapselung zu erzwingen und eine leichtgewichtige methodenähnliche Funktion anzubieten. Es ist nur eine schlechte Praxis, Felder als öffentlich zu deklarieren, aber es gibt keine Probleme.

Brahim Boulkriat
quelle
4

Felder sind normale Mitgliedsvariablen oder Mitgliedsinstanzen einer Klasse. Eigenschaften sind eine Abstraktion, um ihre Werte abzurufen und festzulegen . Eigenschaften werden auch als Accessoren bezeichnet, da sie eine 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;}

  }
Vasim Shaikh
quelle
3

Eigenschaften kapseln Felder, sodass Sie zusätzliche Verarbeitung für den Wert vornehmen können, der festgelegt oder abgerufen werden soll. Die Verwendung von Eigenschaften ist in der Regel übertrieben, wenn Sie keine Vor- oder Nachbearbeitung für den Feldwert durchführen.

Erik Burger
quelle
1
Nein, ich verwende immer Eigenschaften. Dadurch können Sie die Implementierung jederzeit flexibel ändern, ohne Ihre API zu beschädigen.
Sekhat
In Bezug auf die API-Entwicklung können Sie problemlos Felder für private Daten verwenden. Auch in ungeraden Fällen, in denen Sie Daten innerhalb einer Baugruppe freigeben möchten, können Sie den Feldern "internen" Zugriff gewähren.
Daniel Earwicker
3

IMO, Eigenschaften sind nur die "SetXXX ()" "GetXXX ()" - Funktionen / Methoden / Schnittstellenpaare, die wir zuvor verwendet haben, aber sie sind prägnanter und eleganter.

Junchao Xu
quelle
3

Traditionell werden private Felder über Getter- und Setter-Methoden festgelegt. Um weniger Code zu erhalten, können Sie stattdessen Eigenschaften verwenden, um Felder festzulegen.

Chris Paine
quelle
3

wenn Sie eine Klasse haben, die "Auto" ist. Die Eigenschaften sind Farbe, Form ..

Wobei als Felder Variablen sind, die im Bereich einer Klasse definiert sind.

user406580
quelle
3

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 , die häufig als Attribute bezeichnet werden. und Code in Form von Prozeduren, die oft als Methoden bezeichnet werden . (Betonung hinzugefügt)

Eigenschaften sind tatsächlich Teil des Verhaltens eines Objekts, sollen den Verbrauchern des Objekts jedoch die Illusion / Abstraktion geben, mit den Daten des Objekts zu arbeiten.

Zev Spitz
quelle
3

Mein Entwurf eines Feldes ist, dass ein Feld nur von seinem übergeordneten Feld 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 zu lesen, gehe ich nur mit Get durch das Eigenschaftssystem. Das Feld wird dann von der Eigenschaft abgerufen und ist schreibgeschützt! Wenn Sie es ändern möchten, müssen Sie Methoden (zum Beispiel den Konstruktor) durchlaufen, und ich finde, dass wir dank dieser Art der Sicherheit eine bessere Kontrolle über unseren Code haben, weil wir "flanschen". Man könnte sehr gut immer alles öffentlich machen, so dass jeder mögliche Fall, der Begriff der Variablen / Methoden / Klassen usw. meiner Meinung nach nur eine Hilfe für die Entwicklung, Pflege des Codes ist. Wenn eine Person beispielsweise einen Code mit öffentlichen Feldern wieder aufnimmt, kann sie alles und damit "unlogische" Dinge tun. in Bezug auf das Ziel die Logik, warum der Code geschrieben wurde. Es ist mein Standpunkt.

Wenn ich ein klassisches Modell für private Felder / öffentliche schreibgeschützte Eigenschaften verwende, sollte ich für 10 private Felder 10 öffentliche Eigenschaften schreiben! Der Code kann sehr schnell größer sein. Ich entdecke den privaten Setter und benutze 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;
 }
}
Tony Pinot
quelle
Ja mein schlechtes, sorry!
Tony Pinot
3

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 Eigenschaften verwenden, da diese sonst keine Tür darstellen und jeder ohne Vorschrift problemlos hereinkommt

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 haben Sie die Person überprüft und wissen, ob sie etwas Böses bei sich hat

user8080469
quelle
3

Felder sind die Variablen in Klassen. Felder sind die Daten, die Sie mithilfe von Zugriffsmodifikatoren kapseln können.

Eigenschaften sind Feldern insofern ähnlich, als sie Zustände und die einem Objekt zugeordneten Daten definieren.

Im Gegensatz zu einem Feld verfügt eine Eigenschaft über 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.

Neil Meyer
quelle
2

Eigenschaften sind spezielle Arten von Klassenmitgliedern. In Eigenschaften verwenden wir eine vordefinierte Set- oder Get-Methode. Sie verwenden Accessoren, mit denen wir die Werte der privaten Felder lesen, schreiben oder ändern können.

Nehmen wir zum Beispiel eine Klasse Employeemit 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?

Es ist riskant, das Klassenfeld öffentlich zu machen und es verfügbar zu machen, da Sie nicht die Kontrolle darüber haben, was zugewiesen und zurückgegeben wird.

Um dies anhand eines Beispiels klar zu verstehen, nehmen wir eine Schülerklasse mit Ausweis, Passmarke und Name. Nun in diesem Beispiel ein Problem mit dem öffentlichen Feld

  • ID sollte nicht -ve sein.
  • Der Name kann nicht auf null gesetzt werden
  • Pass Mark sollte schreibgeschützt sein.
  • Wenn der Name des Schülers fehlt, sollte kein Name zurückgegeben werden.

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 and 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;
    }
}
ahmed Alkhatib
quelle
2

Zusätzliche Informationen: Standardmäßig sind get- und set-Accessoren genauso zugänglich wie die Eigenschaft selbst. Sie können die Zugänglichkeit von Accessoren individuell steuern / einschränken (zum Abrufen und Festlegen), indem Sie restriktivere Zugriffsmodifikatoren auf sie anwenden.

Beispiel:

public string Name
{
    get
    {
        return name;
    }
    protected set
    {
        name = value;
    }
}

Hier wird auf get immer noch öffentlich zugegriffen (da die Eigenschaft öffentlich ist), aber set ist geschützt (ein eingeschränkter Zugriffsspezifizierer).

code_doctor
quelle
2

Eigenschaften werden verwendet, um Felder verfügbar zu machen. Sie verwenden Accessoren (set, get), mit denen die Werte der privaten Felder gelesen, geschrieben oder bearbeitet 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 wird.

Zum Beispiel haben wir ein privates ganzzahliges Feldalter, 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 verwenden und Eigenschaft 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 wir in get- und set-Accessoren keine Logik verwenden, können wir die automatisch implementierte Eigenschaft verwenden.

Wenn Sie automatisch implementierte Eigenschaftskompilierungen verwenden, wird ein privates, anonymes Feld erstellt , 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 eine Eigenschaft privat festlegen. Hier können wir die Eigenschaft auto privat festlegen (in der Klasse mit).

public int MyProperty
{
    get; private set;
}

Sie können dasselbe mit diesem Code erreichen. In dieser Eigenschaft ist die Funktion nicht verfügbar, da der Wert direkt auf das Feld festgelegt werden muss.

private int myProperty;
public int MyProperty
{
    get { return myProperty; }
}
Nayas Subramanian
quelle
2

In den allermeisten Fällen handelt es sich um einen Eigenschaftsnamen, auf den Sie zugreifen, im Gegensatz zu einem Variablennamen ( Feld ). Der Grund dafür ist, dass dies in .NET und insbesondere in C # als bewährte Methode angesehen wird, um alle Daten innerhalb einer Klasse zu schützen , ob es sich um eine Instanzvariable oder eine statische Variable (Klassenvariable) handelt, da sie einer Klasse zugeordnet ist.

Schützen Sie alle diese Variablen mit entsprechenden Eigenschaften, mit denen Sie Accessoren definieren, festlegen und abrufen sowie Validierungen durchführen können, wenn Sie diese Daten bearbeiten.

In anderen Fällen wie der 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, benötigen wir nicht mehrere Kopien von PI, es wird immer der gleiche Wert sein. Daher werden manchmal statische Variablen verwendet, um Daten zwischen Objekten einer Klasse gemeinsam zu nutzen. Diese Variablen werden jedoch häufig auch für konstante Informationen verwendet, bei denen Sie nur eine Kopie eines Datenelements benötigen.

Nermien Barakat
quelle