c# - tag - Was ist der Unterschied zwischen einem Feld und einer Eigenschaft?




c# using tag (20)

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 nur für Variablen verwenden, die über eine private oder geschützte Zugriffsmöglichkeit verfügen . Daten, die Ihre Klasse dem Client-Code zur Verfügung stellt, sollten durch Methoden, Eigenschaften und Indexer bereitgestellt werden. Wenn 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 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 Methoden, die Accessoren genannt werden . Dies ermöglicht den einfachen Zugriff auf Daten und trägt weiterhin zur Erhöhung der Sicherheit und Flexibilität von Methoden bei . 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.

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


(Dies sollte wirklich ein Kommentar sein, aber ich kann keinen Kommentar posten, also bitte entschuldigen Sie, wenn es nicht als Post geeignet ist).

Ich habe einmal an einem Ort gearbeitet, an dem es empfohlen wurde, öffentliche Felder anstelle von Eigenschaften zu verwenden, wenn die entsprechende Eigenschaft def gerade 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 erschien mir zu dieser Zeit etwas seltsam. Nach diesen Posts zu urteilen, scheint es, als würden sich auch viele hier nicht einigen. Was hättest du sagen sollen, um etwas zu ändern?

Bearbeiten: Ich sollte hinzufügen, dass die gesamte Codebasis an diesem Ort zur gleichen Zeit kompiliert wurde, so dass sie vielleicht gedacht haben, dass das Ändern der öffentlichen Schnittstelle von Klassen (durch Ändern eines öffentlichen Felds in eine Eigenschaft) kein Problem war.


Aus Wikipedia - Objektorientierte Programmierung :

Objektorientierte Programmierung (OOP) ist ein Programmierparadigma, das auf dem Konzept von "Objekten" basiert, bei denen es sich um Datenstrukturen handelt, die Daten in Form von Feldern enthalten , die oft als Attribute bezeichnet werden; und Code, in Form von Verfahren, oft als Methoden bekannt . (Betonung hinzugefügt)

Eigenschaften sind eigentlich ein Teil des Verhaltens eines Objekts, sind aber dafür gedacht, den Konsumenten des Objekts die Illusion / Abstraktion zu geben, mit den Daten des Objekts zu arbeiten.


Da viele von ihnen mit technischen Vor- und Nachteilen von Properties und Field , ist es Zeit, in Echtzeit-Beispiele zu kommen.

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

Betrachten Sie den Fall von dataTable.Rows.Count und dataTable.Columns[i].Caption . Sie stammen aus der Klasse DataTable und beide sind für uns öffentlich. Der Unterschied in der Zugriffsebene zu ihnen ist, dass wir keinen Wert auf dataTable.Rows.Count setzen können, aber wir können lesen und schreiben in dataTable.Columns[i].Caption . Ist das durch Field möglich? Nein!!! Dies kann nur mit 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

Sie haben möglicherweise mit Button in Visual Studio gearbeitet. Seine Eigenschaften werden im PropertyGrid wie Text , Name usw. angezeigt. Wenn wir eine Schaltfläche ziehen und ablegen und auf die Eigenschaften klicken, findet sie automatisch die Klasse Button und filtert Properties und zeigt dies in PropertyGrid (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 Attributes annehmen können. Es wird nicht [Browsable(false)] 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 der 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 Properties dafür verwenden.

5. Debugging-Modus

Überlegen Sie, dass wir 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, zu tun, wo die Anzahl der Codezeilen mehr als 1000 ist. In solchen Situationen können wir Property und den Debug-Modus in Property .

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


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


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.


Eigenschaften sind eine besondere Art von Klassenmember. In Eigenschaften verwenden wir eine vordefinierte Set- oder Get-Methode. Sie verwenden Accessoren, über die 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, age und Employee_Id. Wir können nicht von außerhalb der Klasse auf diese Felder zugreifen, aber wir können auf diese privaten Felder über Eigenschaften zugreifen.

Warum verwenden wir Eigenschaften?

Es ist riskant, das Klassenfeld öffentlich zu machen und es offenzulegen, da Sie nicht kontrollieren können, was zugewiesen und zurückgegeben wird.

Um dies mit einem Beispiel klar zu verstehen, nehmen Sie eine Schülerklasse mit ID, Passwort, Name. Jetzt in diesem Beispiel ein Problem mit dem öffentlichen Feld

  • ID sollte nicht -ve sein.
  • Name kann nicht auf null festgelegt werden
  • Pass-Marke sollte nur gelesen werden.
  • Wenn der Name des Schülers fehlt, sollte kein Name zurückgegeben werden.

Um dieses Problem zu beheben, verwenden wir die Get-Methode.

// 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
    }
}

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

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.


Felder sind gewöhnliche Membervariablen oder Memberinstanzen einer Klasse. Eigenschaften sind eine Abstraktion, um ihre Werte zu erhalten und festzulegen . Eigenschaften werden auch als Zugriffsmethoden bezeichnet, da sie eine Möglichkeit bieten, ein Feld zu ändern und abzurufen, wenn Sie ein Feld in der Klasse als privat freigeben. Im Allgemeinen sollten Sie Ihre Membervariablen als privat deklarieren und dann Eigenschaften für sie deklarieren oder definieren.

  class SomeClass
  {
     int numbera; //Field

     //Property 
    public static int numbera { get; set;}

  }

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

  • Lazy Initialization ( Lazy-Initialisierung) : Wenn Sie eine Eigenschaft eines Objekts haben, deren Laden teuer ist, auf die 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.
  • Dirty Tracking: Was ich über meine eigene Frage hier auf erfahren habe. 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.

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


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

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
}

Traditionell werden private Felder über Getter- und Setter-Methoden gesetzt. Aus Gründen weniger Code können Sie stattdessen Eigenschaften verwenden, um Felder festzulegen.


Wenn Sie Thread-Primitive verwenden, müssen Sie Felder verwenden. Eigenschaften können den Thread-Code unterbrechen. Abgesehen davon, was Cory gesagt hat, ist richtig.


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

Wobei als Felder Variablen definiert sind, die innerhalb des Bereichs einer Klasse definiert sind.


Additional info: By default, get and set accessors are as accessible as the property itself. You can control/restrict accessor accessibility individually (for get and set) by applying more restrictive access modifiers on them.

Beispiel:

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

Here get is still publicly accessed (as the property is public), but set is protected (a more restricted access specifier).


The vast majority of cases it's going to be a property name that you access as opposed to a variable name ( field ) The reason for that is it's considered good practice in .NET and in C# in particular to protect every piece of data within a class, whether it's an instance variable or a static variable (class variable) because it's associated with a class.

Protect all of those variables with corresponding properties which allow you to define, set and get accessors and do things like validation when you're manipulating those pieces of data.

But in other cases like Math class (System namespace), there are a couple of static properties that are built into the class. one of which is the math constant PI

z.B. Math.PI

and because PI is a piece of data that is well-defined, we don't need to have multiple copies of PI, it always going to be the same value. So static variables are sometimes used to share data amongst object of a class, but the are also commonly used for constant information where you only need one copy of a piece of data.


Think about it : You have a room and a door to enter this room. If you want to check how who is coming in and secure your room, then you should use properties otherwise they won't be any door and every one easily come in w/o any regulation

class Room {
   public string sectionOne;
   public string sectionTwo;
}

Room r = new Room();
r.sectionOne = "enter";

Die Leute kommen sehr schnell in die Abteilung hinein, 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 er etwas Böses mit ihm hat





field