c# get - Qual è la differenza tra un campo e una proprietà?




set automatico (25)

In C #, cosa rende un campo diverso da una proprietà e quando dovrebbe essere usato un campo al posto di una proprietà?


Answers

Sullo sfondo una proprietà è compilata in metodi. Quindi una proprietà Name è compilata in get_Name() e set_Name(string value) . Puoi vedere questo se studi il codice compilato. Quindi c'è un sovraccarico di prestazioni (molto) piccolo quando li si usa. Normalmente si utilizzerà sempre una proprietà se si espone un campo all'esterno e lo si utilizzerà spesso internamente se è necessario eseguire la convalida del valore.


Le proprietà sono un tipo speciale di membro della classe. Nelle proprietà utilizziamo un metodo Set o Get predefinito. Utilizzano gli accessor tramite i quali possiamo leggere, scrivere o modificare i valori dei campi privati.

Ad esempio, prendiamo una classe di nome Employee , con campi privati ​​per nome, età e Employee_Id. Non possiamo accedere a questi campi dall'esterno della classe, ma possiamo accedere a questi campi privati ​​attraverso le proprietà.

Perché usiamo le proprietà?

Rendere pubblico il campo classe ed esporlo è rischioso, in quanto non si avrà il controllo di ciò che viene assegnato e restituito.

Per comprenderlo chiaramente con un esempio, prendi una classe studentesca che ha ID, passmark, nome. Ora in questo esempio qualche problema con il campo pubblico

  • L'ID non dovrebbe essere -ve.
  • Il nome non può essere impostato su null
  • Il contrassegno deve essere letto solo
  • Se manca il nome dello studente, nessun nome deve essere restituito.

Per rimuovere questo problema Usiamo il metodo Get e 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
    }
}

Ora prendiamo un esempio di metodo get e 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;
    }
}

Quando vuoi che la tua variabile privata (campo) sia accessibile all'oggetto della tua classe da altre classi devi creare proprietà per tali variabili.

per esempio se ho variabili chiamate "id" e "name" che sono private ma potrebbe esserci una situazione in cui questa variabile è necessaria per operazioni di lettura / scrittura al di fuori della classe. In questa situazione, la proprietà può aiutarmi a ottenere quella variabile in lettura / scrittura a seconda del risultato / set definito per la proprietà. Una proprietà può essere sia readonly / writeonly / readwrite.

ecco la 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";
    }
}

(Questo dovrebbe essere davvero un commento, ma non posso pubblicare un commento, quindi scusami se non è appropriato come post).

Una volta ho lavorato in un luogo in cui lo studio consigliato consisteva nell'utilizzare i campi pubblici anziché le proprietà quando la def equivalente della proprietà avrebbe appena dovuto accedere a un campo, come in:

get { return _afield; }
set { _afield = value; }

Il loro ragionamento era che il campo pubblico poteva essere convertito in una proprietà più tardi in futuro, se necessario. Mi è sembrato un po 'strano in quel momento. A giudicare da questi post, sembra che non molti qui sarebbero d'accordo. Cosa potevi dire per cercare di cambiare le cose?

Edit: Devo aggiungere che tutto il codice base in questo posto è stato compilato allo stesso tempo, quindi avrebbero potuto pensare che cambiare l'interfaccia pubblica delle classi (cambiando un campo pubblico in una proprietà) non fosse un problema.


quando hai una classe che è "Car". Le proprietà sono colore, forma ..

Dove i campi sono variabili definite nell'ambito di una classe.


Ti darò un paio di esempi di utilizzo di proprietà che potrebbero far girare gli ingranaggi:

  • Inizializzazione pigra : se si dispone di una proprietà di un oggetto che è costoso da caricare, ma non si accede a tutto ciò nelle normali esecuzioni del codice, è possibile ritardarne il caricamento tramite la proprietà. In questo modo, è solo seduto lì, ma la prima volta che un altro modulo tenta di chiamare quella proprietà, controlla se il campo sottostante è nullo - se lo è, va avanti e lo carica, sconosciuto al modulo chiamante. Ciò può velocizzare notevolmente l'inizializzazione dell'oggetto.
  • Tracciamento sporco: che in realtà ho imparato dalla mia stessa domanda qui su . Quando ho molti oggetti che i valori potrebbero essere cambiati durante una corsa, posso usare la proprietà per tenere traccia se devono essere salvati nel database o meno. Se non è stata modificata una singola proprietà di un oggetto, il flag IsDirty non verrà attivato, e quindi la funzionalità di salvataggio salterà su di esso al momento di decidere cosa è necessario tornare al database.

Tecnicamente, non penso che ci sia una differenza, perché le proprietà sono solo wrapper attorno ai campi creati dall'utente o creati automaticamente dal compilatore. Lo scopo delle proprietà è quello di rafforzare l'incapsulamento e offrire una funzionalità simile a un metodo leggero. È semplicemente una cattiva pratica dichiarare i campi come pubblici, ma non ha alcun problema.


Usando Properties, puoi lanciare un evento, quando il valore della proprietà viene modificato (aka. PropertyChangedEvent) o prima che il valore venga modificato per supportare l'annullamento.

Questo non è possibile con i campi (accesso diretto a).

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

DIFFERENZE - USI (quando e perché)

Un campo è una variabile dichiarata direttamente in una classe o in una struttura. Una classe o una struttura possono avere campi di istanza o campi statici o entrambi. In genere, è necessario utilizzare i campi solo per le variabili che dispongono di accessibilità privata o protetta . I dati che la tua classe espone al codice cliente dovrebbero essere forniti attraverso metodi, proprietà e indicizzatori. Utilizzando questi costrutti per l'accesso indiretto ai campi interni, è possibile proteggersi da valori di input non validi.

Una proprietà è un membro che fornisce un meccanismo flessibile per leggere, scrivere o calcolare il valore di un campo privato. Le proprietà possono essere utilizzate come se fossero membri di dati pubblici, ma in realtà sono metodi speciali chiamati accessor . Ciò consente di accedere facilmente ai dati e contribuisce a promuovere la sicurezza e la flessibilità dei metodi . Le proprietà consentono a una classe di esporre un metodo pubblico per ottenere e impostare valori, nascondendo il codice di implementazione o di verifica. Una proprietà di accesso get viene utilizzata per restituire il valore della proprietà e un accessor set viene utilizzato per assegnare un nuovo valore.


Da Wikipedia - Programmazione orientata agli oggetti :

La programmazione orientata agli oggetti (OOP) è un paradigma di programmazione basato sul concetto di "oggetti", che sono strutture di dati che contengono dati, sotto forma di campi , spesso noti come attributi; e codice, sotto forma di procedure, spesso conosciute come metodi . (enfasi aggiunta)

Le proprietà sono in realtà parte del comportamento di un oggetto, ma sono progettate per fornire ai consumatori dell'oggetto l'illusione / astrazione del lavoro con i dati dell'oggetto.


Tradizionalmente i campi privati ​​sono impostati tramite metodi getter e setter. Per motivi di meno codice è possibile utilizzare le proprietà per impostare i campi.


Le proprietà hanno il vantaggio principale di consentire di modificare il modo in cui si accede ai dati su un oggetto senza rompere la sua interfaccia pubblica. Ad esempio, se è necessario aggiungere una convalida aggiuntiva o modificare un campo memorizzato in un calcolo, è possibile farlo facilmente se inizialmente esposto il campo come proprietà. Se hai appena esposto un campo direttamente, dovresti modificare l'interfaccia pubblica della tua classe per aggiungere la nuova funzionalità. Quel cambiamento potrebbe rompere i client esistenti, richiedendo loro di essere ricompilati prima che potessero usare la nuova versione del tuo codice.

Se si scrive una libreria di classi progettata per un consumo ampio (come .NET Framework, che viene utilizzato da milioni di persone), ciò può rappresentare un problema. Tuttavia, se stai scrivendo una classe usata internamente in una piccola base di codice (diciamo <= 50 linee K), non è davvero un grosso problema, perché nessuno potrebbe essere influenzato negativamente dalle tue modifiche. In tal caso, si tratta solo di preferenze personali.


La stragrande maggioranza dei casi sarà un nome di proprietà a cui si accede in contrapposizione a un nome di variabile ( campo ) La ragione di ciò è considerata buona pratica in .NET e in C # in particolare per proteggere ogni parte di dati all'interno di una classe , che si tratti di una variabile di istanza o di una variabile statica (variabile di classe) perché è associata a una classe.

Proteggi tutte queste variabili con proprietà corrispondenti che ti permettono di definire, impostare e ottenere accessors e fare cose come la validazione quando stai manipolando quei pezzi di dati.

Ma in altri casi come la classe Math (System namespace), ci sono un paio di proprietà statiche che sono incorporate nella classe. uno dei quali è la costante matematica PI

per esempio. Math.PI

e poiché PI è un pezzo di dati ben definito, non è necessario disporre di più copie di PI, sarà sempre lo stesso valore. Quindi le variabili statiche sono talvolta utilizzate per condividere i dati tra gli oggetti di una classe, ma sono anche comunemente usati per informazioni costanti in cui è necessaria solo una copia di un pezzo di dati.


La seconda domanda qui, "quando un campo dovrebbe essere usato al posto di una proprietà?", Viene solo brevemente accennata in questa altra risposta e anche questa , ma non in molti dettagli.

In generale, tutte le altre risposte sono chiare sul buon design: preferiscono esporre le proprietà oltre i campi di esposizione. Mentre probabilmente non ti troverai regolarmente a dire "wow, immagina quante cose peggiori sarebbero se avessi fatto di questo un campo invece di una proprietà", è molto più raro pensare a una situazione in cui potresti dire "wow, grazie a Dio ho usato un campo qui invece di una proprietà ".

Ma c'è un vantaggio che i campi hanno sulle proprietà, e questa è la loro capacità di essere usati come parametri "ref" / "out". Supponiamo di avere un metodo con la seguente firma:

public void TransformPoint(ref double x, ref double y);

e supponiamo che tu voglia usare quel metodo per trasformare un array creato in questo modo:

System.Windows.Point[] points = new Point[1000000];
Initialize(points);

Ecco, penso che il modo più veloce per farlo, poiché X e Y sono proprietà:

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

E sarà abbastanza buono! A meno che tu non abbia misurazioni che dimostrano il contrario, non c'è motivo di gettare una puzza. Ma credo che non sia tecnicamente garantito essere così veloce come questo:

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

Effettuando alcune measurements solo, la versione con i campi richiede circa il 61% del tempo come versione con proprietà (.NET 4.6, Windows 7, x64, modalità di rilascio, nessun debugger collegato). Quanto più costoso diventa il metodo TransformPoint , tanto meno pronunciato diventa la differenza. Per ripetere tu stesso, corri con la prima riga commentata e con essa non commentata.

Anche se non ci sono benefici per le prestazioni di cui sopra, ci sono altri luoghi in cui la possibilità di utilizzare i parametri ref e out potrebbe essere utile, come quando si chiama la famiglia di metodi Interlocked o Volatile . Nota: nel caso in cui questo sia nuovo per te, Volatile è fondamentalmente un modo per ottenere lo stesso comportamento fornito dalla parola chiave volatile . Come tale, come volatile , non risolve magicamente tutti i problemi legati alla sicurezza del thread, come suggerisce il nome stesso.

Sicuramente non voglio sembrare come se stessi sostenendo che tu vai "oh, dovrei iniziare a esporre campi invece di proprietà". Il punto è che se hai bisogno di usare regolarmente questi membri in chiamate che prendono parametri "ref" o "out", specialmente su qualcosa che potrebbe essere un semplice tipo di valore che è improbabile che abbia mai bisogno di uno qualsiasi degli elementi a valore aggiunto delle proprietà, un argomento può essere fatto.


Pensaci: hai una stanza e una porta per entrare in questa stanza. Se vuoi verificare come chi entra e proteggere la tua stanza, allora dovresti usare le proprietà altrimenti non saranno porte e tutti entreranno facilmente senza alcuna regolamentazione

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

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

La gente sta entrando nella sezione abbastanza facilmente, non c'è stato alcun controllo

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";

Ora hai controllato la persona e sai se ha qualcosa di malvagio con lui


Proprietà espone campi. I campi dovrebbero (quasi sempre) essere mantenuti privati ​​in una classe e accessibili tramite le proprietà get e set. Le proprietà forniscono un livello di astrazione che consente di modificare i campi senza influire sul modo esterno a cui accedono le cose che usano la classe.

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 sottolinea che le proprietà non sono richieste per incapsulare i campi, potrebbero eseguire un calcolo su altri campi o servire ad altri scopi.

@GSS sottolinea che puoi anche fare altra logica, come la convalida, quando si accede a una proprietà, un'altra caratteristica utile.


Le proprietà supportano l'accesso asimmetrico, ovvero puoi avere un getter e un setter o solo uno dei due. Allo stesso modo le proprietà supportano l'accessibilità individuale per getter / setter. I campi sono sempre simmetrici, ovvero puoi sempre ottenere e impostare il valore. Eccezione a ciò sono i campi di sola lettura che ovviamente non possono essere impostati dopo l'inizializzazione.

Le proprietà possono funzionare per un tempo molto lungo, avere effetti collaterali e possono anche generare eccezioni. I campi sono veloci, senza effetti collaterali e non generano mai eccezioni. A causa di effetti collaterali, una proprietà può restituire un valore diverso per ogni chiamata (come potrebbe essere il caso per DateTime.Ora, ad esempio DateTime.Ora non è sempre uguale a DateTime.Now). I campi restituiscono sempre lo stesso valore.

I campi possono essere usati per i parametri out / ref, le proprietà no. Le proprietà supportano la logica aggiuntiva, che potrebbe essere utilizzata per implementare il caricamento lazy tra le altre cose.

Le proprietà supportano un livello di astrazione incapsulando qualsiasi cosa significhi ottenere / impostare il valore.

Utilizzare le proprietà nella maggior parte / tutti i casi, ma cercare di evitare effetti collaterali.


Una differenza importante è che le interfacce possono avere proprietà ma non campi. Questo, per me, sottolinea che le proprietà dovrebbero essere utilizzate per definire l'interfaccia pubblica di una classe mentre i campi sono pensati per essere utilizzati nei meccanismi interni privati ​​di una classe. Di regola raramente creo campi pubblici e, analogamente, raramente creo proprietà non pubbliche.


I campi sono variabili membro ordinarie o istanze membro di una classe. Le proprietà sono un'astrazione per ottenere e impostare i loro valori . Le proprietà sono anche denominate accessors perché offrono un modo per cambiare e recuperare un campo se si espone un campo nella classe come privato. In generale, è necessario dichiarare le proprie variabili membro private, quindi dichiarare o definire proprietà per esse.

  class SomeClass
  {
     int numbera; //Field

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

  }

Inoltre, le proprietà consentono di utilizzare la logica quando si impostano i valori.

Quindi puoi dire che vuoi solo impostare un valore su un campo intero, se il valore è maggiore di x, altrimenti lanciare un'eccezione.

Caratteristica davvero utile


Le proprietà sono usate per esporre il campo. Usano gli accessor (set, get) attraverso i quali i valori dei campi privati ​​possono essere letti, scritti o manipolati.

Le proprietà non nominano le posizioni di memoria. Invece, hanno accessor che leggono, scrivono o calcolano i loro valori.

Usando le proprietà possiamo impostare la validazione sul tipo di dati che è impostato su un campo.

Ad esempio, abbiamo un'età del campo intero privato su cui dovremmo consentire valori positivi poiché l'età non può essere negativa.

Possiamo farlo in due modi usando getter e setter e usando proprietà.

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

Proprietà Auto Implementata se non eseguiamo la logica in get e set accessors possiamo usare la proprietà auto implementata.

Quando la compilazione di proprietà auto-implementata crea un campo privato, anonimo a cui è possibile accedere solo tramite get e set accessors.

public int Age{get;set;}

Proprietà astratte Una classe astratta può avere una proprietà astratta, che dovrebbe essere implementata nella classe derivata

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

Possiamo impostare privatamente una proprietà In questo possiamo impostare privatamente la proprietà auto (impostata con nella classe)

public int MyProperty
{
    get; private set;
}

Puoi ottenere lo stesso con questo codice. In questa funzione di proprietà non è disponibile in quanto dobbiamo impostare direttamente il valore sul campo.

private int myProperty;
public int MyProperty
{
    get { return myProperty; }
}

I principi di programmazione orientati agli oggetti dicono che i meccanismi interni di una classe dovrebbero essere nascosti al mondo esterno. Se esponi un campo, in sostanza stai esponendo l'implementazione interna della classe. Quindi avvolgiamo campi con Proprietà (o metodi nel caso di Java) per darci la possibilità di cambiare l'implementazione senza infrangere il codice a seconda di noi. Vedere come possiamo inserire la logica nella proprietà ci consente anche di eseguire la logica di convalida ecc. Se ne abbiamo bisogno. C # 3 ha la nozione, forse confusa, di autoproprietà. Questo ci permette di definire semplicemente la proprietà e il compilatore C # 3 genererà il campo privato per noi.

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
}


Se si intende utilizzare le primitive del thread, si è obbligati a utilizzare i campi. Le proprietà possono rompere il codice filettato. A parte ciò, ciò che ha detto è corretto.


C'è una piccola differenza tra i campi const e static readonly in C # .Net

const deve essere inizializzato con valore in fase di compilazione.

const è di default statico e deve essere inizializzato con un valore costante, che non può essere modificato in seguito. Non può essere utilizzato con tutti i tipi di dati. Per ex-DateTime. Non può essere utilizzato con datatype DateTime.

public const DateTime dt = DateTime.Today;  //throws compilation error
public const string Name = string.Empty;    //throws compilation error
public static readonly string Name = string.Empty; //No error, legal

readonly può essere dichiarato come statico, ma non necessario. Non è necessario inizializzarsi al momento della dichiarazione. Il suo valore può essere assegnato o modificato usando il costruttore una volta. Quindi c'è la possibilità di cambiare il valore del campo di sola lettura una volta (non importa, se è statico o meno), che non è possibile con const.





c# properties field