Proprietà vs metodi


135

Domanda veloce: quando decidi di usare le proprietà (in C #) e quando decidi di usare i metodi?

Siamo impegnati in questo dibattito e abbiamo trovato alcune aree in cui è discutibile se dovremmo usare una proprietà o un metodo. Un esempio è questo:

public void SetLabel(string text)
{
    Label.Text = text;
}

Nell'esempio, Labelè un controllo su una pagina ASPX. Esiste un principio che può governare la decisione (in questo caso) se rendere questo un metodo o una proprietà.

Accetterò la risposta più generale e completa, ma che tocca anche l'esempio che ho dato.


2
-1 questa domanda è stata posta e risposta prima: stackoverflow.com/questions/164527/…
Elemento

I pro e contro del metodo / campo / proprietà possono generare lunghi dibattiti; qualche uso generale per le proprietà: quando vuoi campi privati ​​/ protetti ma allo stesso tempo vuoi esporli. Un altro uso è quello di avere non solo le dichiarazioni ma anche le espressioni (azioni se vuoi) anche i if()controlli (come da MSDN). Ma questo è difficile poiché l'utente non è sempre consapevole del costo di elaborazione dietro l'accesso a una variabile (proprietà) (cioè il codice non è disponibile) e per ragioni di rigore si dovrebbe fare un benchmark della proprietà. Oh, e un "bonus" non puoi usare i puntatori con proprietà.
mireazma,

Risposte:


146

Dalla sezione Scelta tra proprietà e metodi delle Linee guida di progettazione per lo sviluppo di librerie di classi:

In generale, i metodi rappresentano azioni e le proprietà rappresentano i dati. Le proprietà sono pensate per essere usate come campi, il che significa che le proprietà non dovrebbero essere complesse dal punto di vista computazionale o produrre effetti collaterali. Quando non viola le seguenti linee guida, considera l'utilizzo di una proprietà, piuttosto che un metodo, perché gli sviluppatori meno esperti trovano le proprietà più facili da usare.


3
Mentre sono d'accordo con gran parte di ciò, non penso che la parte sugli effetti collaterali sia giusta. Ad esempio, "Colore" è spesso una proprietà di un oggetto e presenta evidenti effetti collaterali (modifica del colore di un oggetto). La modifica delle proprietà ha l'ovvio effetto collaterale della modifica dello stato dell'oggetto.
Erik Funkenbusch,

46
Mystere Man cambia colore è l'effetto desiderato, non l'effetto collaterale. L'effetto collaterale è qualcosa che non è previsto nell'azione primaria.
Muhammad Hasan Khan,

2
@Mystere Man: cambiare definitivamente il colore non è un effetto collaterale, sono completamente d'accordo con questa risposta
Ahmed Said

2
"Perché gli sviluppatori meno esperti trovano le proprietà più facili da usare." - A mio avviso, questo è l'unico motivo per esporre le proprietà. Ma ho ragione?
Tsabo,

2
Qual è la differenza nell'implementazione interna di una proprietà rispetto a un metodo. Qualcosa viene inserito nello stack di chiamate ogni volta che viene utilizzata una proprietà? In caso contrario, in quale altro modo viene gestito?
Praveen,

57

Sì, se tutto ciò che stai facendo è ottenere e impostare, usa una proprietà.

Se stai facendo qualcosa di complesso che può interessare diversi membri dei dati, un metodo è più appropriato. Oppure se il tuo getter accetta parametri o il setter accetta più di un parametro valore.

Nel mezzo c'è un'area grigia in cui la linea può essere leggermente sfocata. Non esiste una regola rigida e veloce e diverse persone a volte non sono d'accordo sul fatto che qualcosa debba essere una proprietà o un metodo. L'importante è essere (relativamente) coerenti con il modo in cui lo fai (o come lo fa il tuo team).

Sono in gran parte intercambiabili ma una proprietà segnala all'utente che l'implementazione è relativamente "semplice". Oh, e la sintassi è un po 'più pulita.

In generale, la mia filosofia è che se inizi a scrivere un nome di metodo che inizia con get o set e accetta zero o un parametro (rispettivamente), allora è un candidato principale per una proprietà.


1
Down-votato. Questo non è corretto La complessità di un getter o setter è incapsulata nel codice getter / setter. Quanto sia complesso non è rilevante, né lo è se "influenza diversi membri di dati" È vero che parametri non standard o multipli richiedono un metodo, ma per il resto questa risposta non è accurata.
Hal50000,

La prima frase spiega tutto. Bravo.
SWIIWII,

13

Le proprietà sono un modo per iniettare o recuperare dati da un oggetto. Creano un'astrazione su variabili o dati all'interno di una classe. Sono analoghi a getter e setter in Java.

I metodi incapsulano un'operazione.

In generale utilizzo le proprietà per esporre singoli bit di dati o piccoli calcoli su una classe, come l'imposta sulle vendite. Quale è derivato dal numero di articoli e dal loro costo in un carrello.

Uso i metodi quando creo un'operazione, come il recupero di dati dal database. Qualsiasi operazione che abbia parti in movimento è un candidato per un metodo.

Nel tuo esempio di codice lo avvolgo in una proprietà se devo accedervi al di fuori della sua classe contenente:

public Label Title 
{
   get{ return titleLabel;}
   set{ titleLabel = value;}
}

Impostazione del testo:

Title.Text = "Properties vs Methods";

Se stessi solo impostando la proprietà Text dell'etichetta, ecco come lo farei:

public string Title 
{
   get{ return titleLabel.Text;}
   set{ titleLabel.Text = value;}
}

Impostazione del testo:

Title = "Properties vs Methods";

12

Se stai impostando una proprietà effettiva del tuo oggetto, allora usi una proprietà.

Se stai eseguendo un'attività / funzionalità, allora usi un metodo.

Nel tuo esempio, è una proprietà definita che viene impostata.

Se tuttavia, la tua funzionalità fosse di AppendToLabel, utilizzeresti un metodo.


11

Cercando tramite MSDN, ho trovato un riferimento su Proprietà vs Metodi che fornisce alcune ottime linee guida per la creazione di metodi:

  • L'operazione è una conversione, ad esempio Object.ToString.
  • L'operazione è abbastanza costosa che si desidera comunicare all'utente che devono considerare la memorizzazione nella cache del risultato.
  • L'ottenimento di un valore di proprietà utilizzando l'accessor get avrebbe un effetto collaterale osservabile.
  • Chiamare il membro due volte in successione produce risultati diversi.
  • L'ordine di esecuzione è importante. Si noti che le proprietà di un tipo dovrebbero poter essere impostate e recuperate in qualsiasi ordine.
  • Il membro è statico ma restituisce un valore che può essere modificato.
  • Il membro restituisce un array. Le proprietà che restituiscono array possono essere molto fuorvianti. Di solito è necessario restituire una copia dell'array interno in modo che l'utente non possa modificare lo stato interno. Questo, unito al fatto che un utente può facilmente supporre che sia una proprietà indicizzata, porta a un codice inefficiente.

Concordo sul fatto che ciò abbia senso laddove applicabile. Ma ho ragione, usare le proprietà tramite l'associazione XAML in WPF non lascia altra scelta che fare le azioni appropriate nel setter? (in particolare su un nuovo SelectedItem per ComboBox, ListBox, ecc.)
Nicolas

9

Basta guardare solo il nome ... "Proprietà". Cosa significa? Il dizionario lo definisce in molti modi, ma in questo caso "un attributo essenziale o distintivo o la qualità di una cosa" si adatta meglio.

Pensa allo scopo dell'azione. Stai, infatti, alterando o recuperando "un attributo essenziale o distintivo"? Nel tuo esempio, stai usando una funzione per impostare una proprietà di una casella di testo. Sembra un po 'sciocco, vero?

Le proprietà sono davvero funzioni. Si compilano tutti in getXXX () e setXXX (). Li nasconde solo nello zucchero sintattico, ma è lo zucchero che fornisce un significato semantico al processo.

Pensa a proprietà come gli attributi. Una macchina ha molti attributi. Colore, MPG, modello, ecc. Non tutte le proprietà sono impostabili, alcune sono calcolabili.

Nel frattempo, un metodo è un'azione. GetColor dovrebbe essere una proprietà. GetFile () dovrebbe essere una funzione. Un'altra regola empirica è che, se non cambia lo stato dell'oggetto, dovrebbe essere una funzione. Ad esempio, CalculatePiToNthDigit (n) dovrebbe essere una funzione, perché in realtà non sta cambiando lo stato dell'oggetto Math a cui è collegato.

Questo forse è un po 'sconclusionato, ma si riduce davvero a decidere quali sono i tuoi oggetti e cosa rappresentano. Se non riesci a capire se dovrebbe essere una proprietà o una funzione, forse non importa quale.


9

Allo stesso modo le proprietà sono attributi dei tuoi oggetti. I metodi sono comportamenti del tuo oggetto.

L'etichetta è un attributo e ha più senso renderla una proprietà.

In termini di programmazione orientata agli oggetti, dovresti avere una chiara comprensione di ciò che fa parte del comportamento e di ciò che è semplicemente un attributo.

Auto {Colore, Modello, Marca}

Un'auto ha gli attributi Color, Model e Brand, quindi non ha senso avere un metodo SetColor o SetModel perché in modo sintetico non chiediamo ad Auto di impostare il proprio colore.

Quindi se mappi il caso proprietà / metodo sull'oggetto reale o lo guardi da un punto di vista simbolico, la tua confusione sparirà davvero.


4

Un altro grande vantaggio di Proprietà è che il valore della proprietà può essere visto in Visual Studio durante il debug.


3

Preferisco usare le proprietà per aggiungere / impostare metodi con 1 parametro. Se i parametri sono maggiori, utilizzare i metodi.


3

Le proprietà devono essere semplicemente impostate e ottenere una sola riga. Qualcosa di più e dovrebbe davvero essere spostato su un metodo. Il codice complesso dovrebbe essere sempre nei metodi.


3

Uso solo le proprietà per l'accesso alle variabili, ovvero ottenere e impostare singole variabili o ottenere e impostare i dati nei controlli. Non appena è necessario / eseguito qualsiasi tipo di manipolazione dei dati, utilizzo i metodi.


3

A livello di progettazione, le proprietà rappresentano dati o attributi dell'oggetto di classe, mentre i metodi sono azioni o comportamenti dell'oggetto di classe.

In .Net, world ci sono altre implicazioni nell'uso di Proprietà:

  • Le proprietà sono utilizzate nel Databinding, mentre i metodi get_ / set_ non lo sono.
  • Proprietà dell'utente di serializzazione XML come meccanismo naturale di serilizzazione.
  • Le proprietà sono accessibili dal controllo PropertyGrid e dall'ICustomTypeDescriptor interno , che può essere utilizzato in modo efficace se si sta scrivendo una libreria personalizzata.
  • Le proprietà sono controllate da Attributi , si può usare saggiamente per progettare software orientati all'aspetto.

Idee sbagliate (IMHO) sull'uso delle Proprietà:

  • Utilizzato per esporre piccoli calcoli: il blocco get di ControlDesigner.SelectionRules viene eseguito su 72 righe !!
  • Utilizzato per esporre strutture di dati interne: anche se una proprietà non è mappata a un membro di dati interno, è possibile utilizzarla come proprietà, se è un attributo della classe. Viceversa, anche se non è consigliabile un attributo delle proprietà della classe, restituisce array come membri di dati (invece i metodi vengono utilizzati per restituire una copia approfondita dei membri).

Nell'esempio qui avrebbe potuto essere scritto, con più significato commerciale come:

public String Title
{
    set { Label.Text = text; }
}

2

Le proprietà sono davvero belle perché sono accessibili nel visual designer di Visual Studio, a condizione che abbiano accesso.

Usano essere usato se si sta semplicemente impostando e ottenendo e forse qualche validazione che non accede a una quantità significativa di codice. Fai attenzione perché la creazione di oggetti complessi durante la convalida non è semplice.

Qualsiasi altro metodo è il modo preferito.

Non si tratta solo di semantica. L'utilizzo di proprietà inappropriate inizia a creare stranezze nel visual designer di Visual Studio.

Ad esempio stavo ottenendo un valore di configurazione all'interno di una proprietà di una classe. La classe di configurazione apre effettivamente un file ed esegue una query sql per ottenere il valore di quella configurazione. Ciò ha causato problemi nella mia applicazione in cui il file di configurazione veniva aperto e bloccato da Visual Studio stesso anziché dalla mia applicazione perché non stava solo leggendo ma scrivendo il valore di configurazione (tramite il metodo setter). Per risolvere questo problema, dovevo solo cambiarlo in un metodo.


1

Ecco una buona serie di linee guida su quando utilizzare le proprietà rispetto ai metodi di Bill Wagner

  • Usa una proprietà quando tutto ciò è vero: i getter dovrebbero essere semplici e quindi improbabili che generino eccezioni. Si noti che ciò non implica alcun accesso alla rete (o al database). Entrambi potrebbero fallire, e quindi genererebbero un'eccezione.
  • Non dovrebbero avere dipendenze reciproche. Si noti che ciò include l'impostazione di una proprietà e la sua influenza su un'altra. (Ad esempio, l'impostazione della proprietà FirstName influirebbe su una proprietà FullName di sola lettura che componeva le proprietà nome + cognome implica tale dipendenza)
  • Dovrebbero essere configurabili in qualsiasi ordine
  • Il getter non ha un effetto collaterale osservabile. Nota: questa linea guida non preclude alcune forme di valutazione pigra in una proprietà.
  • Il metodo deve sempre restituire immediatamente. (Si noti che ciò preclude una proprietà che effettua una chiamata di accesso al database, una chiamata al servizio Web o altre operazioni simili).
  • Utilizzare un metodo se il membro restituisce un array.
  • Le chiamate ripetute al getter (senza codice interposto) dovrebbero restituire lo stesso valore.
  • Le chiamate ripetute al setter (con lo stesso valore) non dovrebbero comportare alcuna differenza rispetto a una singola chiamata.

  • Il get non dovrebbe restituire un riferimento alle strutture di dati interne (vedere il punto 23). Un metodo potrebbe restituire una copia approfondita ed evitare questo problema.

* Tratto dalla mia risposta a una domanda duplicata.


Le risposte più votate e accettate qui stackoverflow.com/a/1294189/1551 Perché il downvote?
Chris Ballance,

2
Mi rendo conto di essere un po 'in ritardo alla festa, ma molto probabilmente il downvote è dovuto al fatto che hai incollato la tua risposta. Incollando la copia, hai ammesso che questa domanda era sostanzialmente un duplicato dell'altra. Pertanto, dovresti averlo contrassegnato come duplicato invece di rispondere. Consiglio di leggere un articolo su Meta per sapere come gestire le domande duplicate.
Giosuè,

0

Questo è semplice

1: utilizzare la proprietà quando si desidera che i dati vengano convalidati prima di essere archiviati nel campo. Quindi in questo modo la proprietà fornisce l'incapsulamento per i tuoi campi. Perché se lasci i tuoi campi l'utente finale pubblico può assegnare qualsiasi valore che può essere o non essere valido in base ai requisiti della tua azienda, ad esempio l'età deve essere maggiore di 18. Quindi, prima che il valore sia archiviato nel campo corrispondente, dobbiamo verificarne la validità. In questo modo le proprietà rappresentano i dati.

2: Utilizzare il metodo quando si desidera eseguire alcune azioni come se si stessero fornendo alcuni dati come parametro e il metodo stia eseguendo l'elaborazione sulla base dei valori forniti e restituendo il valore elaborato come output. Oppure vuoi cambiare il valore di alcuni campi con questo calcolo. "In questo modo il metodo rappresenta l'azione".


-1

Vengo da Java e ho usato get .. set .. metodo per un po '.

Quando scrivo codice, non mi chiedo: "accedere a questi dati è semplice o richiede un processo pesante?" perché le cose possono cambiare (oggi ripristinare questa proprietà è semplice, domani può richiedere un processo pesante o pesante).

Oggi ho un metodo SetAge (int age) domani avrò anche un metodo SetAge (date birthdate) che calcola l'età usando il birthdate.

Sono rimasto molto deluso dal fatto che il compilatore trasformi la proprietà in get e set ma non considero i miei metodi Get ... e Set .. uguali.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.