Perché dovrei evitare di usare le proprietà in C #?


102

Nel suo eccellente libro, CLR Via C #, Jeffrey Richter ha detto che non gli piacciono le proprietà e consiglia di non usarle. Ha dato qualche ragione, ma non capisco davvero. Qualcuno può spiegarmi perché dovrei o non dovrei usare le proprietà? In C # 3.0, con proprietà automatiche, questa modifica?

Come riferimento, ho aggiunto le opinioni di Jeffrey Richter:

• Una proprietà può essere di sola lettura o di sola scrittura; l'accesso al campo è sempre leggibile e scrivibile. Se si definisce una proprietà, è meglio offrire sia i metodi di accesso get che set.

• Un metodo di proprietà può generare un'eccezione; l'accesso al campo non genera mai un'eccezione.

• Una proprietà non può essere passata come parametro out o ref a un metodo; un campo può. Ad esempio, il codice seguente non verrà compilato:

using System;
public sealed class SomeType
{
   private static String Name 
   {
     get { return null; }
     set {}
   }
   static void MethodWithOutParam(out String n) { n = null; }
   public static void Main()
   {
      // For the line of code below, the C# compiler emits the following:
      // error CS0206: A property or indexer may not
      // be passed as an out or ref parameter
      MethodWithOutParam(out Name);
   }
}

• L'esecuzione di un metodo di proprietà può richiedere molto tempo; l'accesso al campo viene sempre completato immediatamente. Un motivo comune per utilizzare le proprietà è eseguire la sincronizzazione del thread, che può arrestare il thread per sempre e, pertanto, una proprietà non deve essere utilizzata se è necessaria la sincronizzazione del thread. In quella situazione, è preferibile un metodo. Inoltre, se è possibile accedere alla classe in remoto (ad esempio, la classe è derivata da System.MashalByRefObject), la chiamata al metodo della proprietà sarà molto lenta e, pertanto, un metodo è preferito a una proprietà. A mio parere, le classi derivate da MarshalByRefObject non dovrebbero mai utilizzare proprietà.

• Se chiamato più volte di seguito, un metodo di proprietà può restituire ogni volta un valore diverso; un campo restituisce ogni volta lo stesso valore. La classe System.DateTime ha una proprietà Now di sola lettura che restituisce la data e l'ora correnti. Ogni volta che si esegue una query su questa proprietà, verrà restituito un valore diverso. Questo è un errore e Microsoft desidera poter correggere la classe rendendo Now un metodo anziché una proprietà.

• Un metodo di proprietà può causare effetti collaterali osservabili; l'accesso al campo non lo fa mai. In altre parole, un utente di un tipo dovrebbe essere in grado di impostare varie proprietà definite da un tipo in qualsiasi ordine scelga senza notare alcun comportamento diverso nel tipo.

• Un metodo di proprietà può richiedere memoria aggiuntiva o restituire un riferimento a qualcosa che non fa effettivamente parte dello stato dell'oggetto, quindi la modifica dell'oggetto restituito non ha alcun effetto sull'oggetto originale; l'interrogazione di un campo restituisce sempre un riferimento a un oggetto che è garantito essere parte dello stato dell'oggetto originale. Lavorare con una proprietà che restituisce una copia può creare confusione per gli sviluppatori e questa caratteristica spesso non è documentata.


11
Possiedo la 3a edizione di "CLR via C #" ea pagina 242 il signor Richter dice che personalmente non gli piacciono le proprietà, ma non consiglia mai di non usarle. Per favore, cita la versione del libro e il numero di pagina dove hai letto questo.
kirk.burleson

Risposte:


173

Il motivo per cui Jeff non ama le proprietà è perché sembrano campi, quindi gli sviluppatori che non capiscono la differenza le tratteranno come se fossero campi, supponendo che siano economici da eseguire ecc.

Personalmente non sono d'accordo con lui su questo punto particolare: trovo che le proprietà rendano il codice client molto più semplice da leggere rispetto alle chiamate al metodo equivalenti. Sono d'accordo sul fatto che gli sviluppatori debbano sapere che le proprietà sono fondamentalmente metodi camuffati, ma penso che educare gli sviluppatori su questo sia meglio che rendere il codice più difficile da leggere usando i metodi. (In particolare, avendo visto il codice Java con diversi getter e setter chiamati nella stessa istruzione, so che l'equivalente codice C # sarebbe molto più semplice da leggere. La Legge di Demetra va molto bene in teoria, ma a volte foo.Name.Lengthlo è davvero la cosa giusta da usare ...)

(E no, le proprietà implementate automaticamente non cambiano nulla di tutto ciò.)

Questo è un po 'come gli argomenti contro l'uso dei metodi di estensione: posso capire il ragionamento, ma il vantaggio pratico (se usato con parsimonia) supera il lato negativo a mio avviso.


Grazie mille per la tua risposta! A proposito di argomenti contro l'utilizzo di metodi di estensione: stai parlando di qualche argomento di Jeffrey Richter o in astratto?
abatishchev

@abatishchev: era solo un punto generale sui metodi di estensione. Non è direttamente correlato alle proprietà.
Jon Skeet,

Andrei oltre. Ad eccezione dell'aspetto delle prestazioni, non vedo perché un programmatore dovrebbe SAPERE se qualcosa è un campo o una proprietà. Dovrebbe considerarlo come l'attributo di un'istanza che designa lo STATO dell'istanza dell'oggetto, e l'implementazione dell'oggetto dovrebbe occuparsi di tutte le modifiche al suo stato (all'interno del contratto della classe). Quindi le proprietà potrebbero anche essere campi in alcuni casi, o diventare campi in altri, se magari si riprogetta l'implementazione della classe. Quindi, decidere tra un campo o una proprietà è una questione di quanta protezione lo stato ha bisogno per rimanere coerente.
TheBlastOne

1
@PatrickFromberg: hai perso una grande quantità di codice che utilizza campi di sola lettura, apparentemente. Non c'è niente da dire che le proprietà implichino la mutabilità. Ho spesso campi di sola lettura che supportano proprietà di sola lettura: pensi che sia una brutta cosa?
Jon Skeet

1
@Patrick: No, porta il vantaggio di separare l'API dall'implementazione: puoi modificare in seguito il modo in cui la proprietà viene calcolata dal campo (ad esempio per calcolare due proprietà correlate da un campo).
Jon Skeet

34

Bene, prendiamo i suoi argomenti uno per uno:

Una proprietà può essere di sola lettura o di sola scrittura; l'accesso al campo è sempre leggibile e scrivibile.

Questa è una vittoria per le proprietà, poiché hai un controllo più preciso dell'accesso.

Un metodo di proprietà può generare un'eccezione; l'accesso al campo non genera mai un'eccezione.

Anche se questo è per lo più vero, puoi benissimo chiamare un metodo su un campo oggetto non inizializzato e ottenere un'eccezione.

• Una proprietà non può essere passata come parametro out o ref a un metodo; un campo può.

Giusto.

• L'esecuzione di un metodo di proprietà può richiedere molto tempo; l'accesso al campo viene sempre completato immediatamente.

Può richiedere anche pochissimo tempo.

• Se chiamato più volte di seguito, un metodo di proprietà può restituire ogni volta un valore diverso; un campo restituisce ogni volta lo stesso valore.

Non vero. Come fai a sapere che il valore del campo non è cambiato (forse da un altro thread)?

La classe System.DateTime ha una proprietà Now di sola lettura che restituisce la data e l'ora correnti. Ogni volta che si esegue una query su questa proprietà, verrà restituito un valore diverso. Questo è un errore e Microsoft desidera poter correggere la classe rendendo Now un metodo anziché una proprietà.

Se è un errore è minore.

• Un metodo di proprietà può causare effetti collaterali osservabili; l'accesso al campo non lo fa mai. In altre parole, l'utente di un tipo dovrebbe essere in grado di impostare varie proprietà definite da un tipo nell'ordine che preferisce senza notare alcun comportamento diverso nel tipo.

Giusto.

• Un metodo di proprietà può richiedere memoria aggiuntiva o restituire un riferimento a qualcosa che non fa effettivamente parte dello stato dell'oggetto, quindi la modifica dell'oggetto restituito non ha alcun effetto sull'oggetto originale; l'interrogazione di un campo restituisce sempre un riferimento a un oggetto che è garantito essere parte dello stato dell'oggetto originale. Lavorare con una proprietà che restituisce una copia può creare confusione per gli sviluppatori e questa caratteristica spesso non è documentata.

La maggior parte delle proteste si potrebbe dire anche per i getter e setter di Java, e li abbiamo avuti per un bel po 'senza tali problemi in pratica.

Penso che la maggior parte dei problemi possa essere risolta con una migliore evidenziazione della sintassi (cioè differenziando le proprietà dai campi) in modo che il programmatore sappia cosa aspettarsi.


3
"i problemi potrebbero essere risolti con una migliore evidenziazione della sintassi" : Quanto spesso usi i campi pubblici? I campi privati ​​di solito hanno uno stile diverso, ad es _field. O anche solo minuscolo field.
Steven Jeuris

18

Non ho letto il libro e non hai citato la parte che non capisci, quindi dovrò indovinare.

Ad alcune persone non piacciono le proprietà perché possono far fare al tuo codice cose sorprendenti.

Se digito Foo.Bar, le persone che lo leggono normalmente si aspettano che questo acceda semplicemente a un campo membro della classe Foo. È un'operazione economica, quasi gratuita, deterministica. Posso chiamarlo più e più volte e ottenere lo stesso risultato ogni volta.

Invece, con le proprietà, potrebbe effettivamente essere una chiamata di funzione. Potrebbe essere un ciclo infinito. Potrebbe aprire una connessione al database. Potrebbe restituire valori diversi ogni volta che accedo.

È un argomento simile al motivo per cui Linus odia il C ++. Il tuo codice può sorprendere il lettore. Odia il sovraccarico dell'operatore: a + bnon significa necessariamente semplice aggiunta. Può significare un'operazione estremamente complicata, proprio come le proprietà C #. Potrebbe avere effetti collaterali. Può fare qualsiasi cosa.

Onestamente, penso che questo sia un argomento debole. Entrambe le lingue sono piene di cose come questa. (Dovremmo evitare l'overloading degli operatori anche in C #? Dopo tutto, lo stesso argomento può essere utilizzato lì)

Le proprietà consentono l'astrazione. Possiamo fingere che qualcosa sia un campo normale e usarlo come se lo fosse, senza doversi preoccupare di ciò che accade dietro le quinte.

Di solito è considerato una buona cosa, ma ovviamente si basa sul programmatore che scrive astrazioni significative. Le tue proprietà dovrebbero comportarsi come i campi. Non dovrebbero avere effetti collaterali, non dovrebbero eseguire operazioni costose o non sicure. Vogliamo essere in grado di pensarli come campi.

Tuttavia, ho un altro motivo per trovarli meno che perfetti. Non possono essere passati facendo riferimento ad altre funzioni.

I campi possono essere passati come ref , consentendo a una funzione chiamata di accedervi direttamente. Le funzioni possono essere passate come delegati, consentendo a una funzione chiamata di accedervi direttamente.

Proprietà ... non possono.

Che fa schifo.

Ma questo non significa che le proprietà siano malvagie o non dovrebbero essere usate. Per molti scopi, sono fantastici.


3
La mia tesi è che non dovresti presumere che sia un campo con cui iniziare, perché se lo chiami da qualsiasi altra classe, non dovresti comunque avere accesso a campi non costanti, perché dovrebbero essere privati. (C'è anche la convenzione di denominazione per informarti.)
Jon Skeet

1
Sì sono d'accordo. L'argomento sembra ridursi a "Sono abituato a questa sintassi utilizzata esclusivamente per i campi. Pertanto, estenderla per coprire altri casi è negativo". E la risposta ovvia è "Bene, abituati a trattare altri casi, e non sarà male". ;)
jalf

Vorrei che i linguaggi .net fornissero un mezzo standard con cui una classe ha proprietà di esposizione come refparametri; un membro (ad esempio Foo) di un form void Foo<T>(ActionByRef<Point,T> proc, ref T param)con un attributo speciale, e fai trasformare il compilatore thing.Foo.X+=someVar;in Foo((ref Point it, ref int param)=>it.X += param, ref someVar);. Poiché lambda è un delegato statico, non sarebbe richiesta alcuna chiusura e l'utente di un oggetto sarebbe in grado di utilizzare qualsiasi posizione di archiviazione supportata dalla proprietà come refparametro autentico (e potrebbe passarla ad altri metodi come refparametro).
supercat

Scrivere il lambda a mano produce codice sorgente dall'aspetto davvero icky, ma è per questo che sarebbe utile che il compilatore esegua la trasformazione. Il codice per una classe per esporre una proprietà "callback-by-ref" sarebbe abbastanza ragionevole. Il codice è solo brutto (assente una trasformazione) dal lato del chiamante.
supercat

Tieni presente che una proprietà è una chiamata di funzione mascherata da membro, quindi non può essere passata per riferimento più di quanto tu possa passare le funzioni pubbliche di una classe. Puoi sempre utilizzare un membro pubblico se intendi farlo in questo modo. Una proprietà è un membro intelligente, può generare un'eccezione per i dati non validi passati a set.
Diceyus

17

Nel 2009, questo consiglio sembrava semplicemente un mal di pancia della varietà Who Moved My Cheese . Oggi è quasi ridicolmente obsoleto.

Un punto molto importante su cui molte risposte sembrano essere in punta di piedi ma che non affrontano direttamente è che questi presunti "pericoli" delle proprietà sono una parte intenzionale del progetto del framework!

Sì, le proprietà possono:

  • Specificare modificatori di accesso diversi per getter e setter. Questo è un vantaggio rispetto ai campi. Un modello comune è quello di avere un getter pubblico e un setter protetto o interno , una tecnica di ereditarietà molto utile che non è realizzabile dai soli campi.

  • Lancia un'eccezione. Ad oggi, questo rimane uno dei metodi di convalida più efficaci, soprattutto quando si lavora con framework di interfaccia utente che implicano concetti di associazione dei dati. È molto più difficile garantire che un oggetto rimanga in uno stato valido quando si lavora con i campi.

  • Ci vuole molto tempo per eseguire. Il confronto valido qui è con metodi , che richiedono campi ugualmente lunghi . Non viene fornita alcuna base per l'affermazione "un metodo è preferito" oltre alla preferenza personale di un autore.

  • Restituisce valori diversi dal suo getter nelle esecuzioni successive. Questo sembra quasi uno scherzo in prossimità del punto che esalta le virtù di ref/ outparameters con i campi, il cui valore di un campo dopo una chiamata ref/ outè praticamente garantito essere diverso dal suo valore precedente, e in modo imprevedibile.

    Se stiamo parlando del caso specifico (e praticamente accademico) di accesso a thread singolo senza accoppiamenti afferenti, è abbastanza ben compreso che è solo una cattiva progettazione di proprietà avere effetti collaterali che cambiano lo stato visibile, e forse la mia memoria lo è dissolvenza, ma non riesco a ricordare alcun esempio di persone che usano DateTime.Nowe si aspettano che lo stesso valore venga fuori ogni volta. Almeno non tutti i casi in cui non avrebbero sbagliato altrettanto male con un ipotetico DateTime.Now().

  • Causa effetti collaterali osservabili, che è ovviamente proprio il motivo per cui le proprietà sono state inventate come caratteristica del linguaggio in primo luogo. Le linee guida di progettazione della proprietà di Microsoft indicano che l'ordine dei setter non dovrebbe avere importanza, poiché altrimenti implicherebbe l' accoppiamento temporale . Certamente, non puoi ottenere l'accoppiamento temporale con i campi da soli, ma è solo perché non puoi causare alcun comportamento significativo con i soli campi, finché non viene eseguito un metodo.

    Le funzioni di accesso alle proprietà possono effettivamente aiutare a prevenire alcuni tipi di accoppiamento temporale forzando l'oggetto in uno stato valido prima che venga intrapresa qualsiasi azione, ad esempio, se una classe ha una StartDatee una EndDate, quindi impostando la EndDateprima di StartDatepotrebbe anche forzare la StartDateschiena. Questo è vero anche in ambienti multi-thread o asincroni, incluso l'ovvio esempio di un'interfaccia utente guidata dagli eventi.

Altre cose che le proprietà possono fare e che i campi non possono includere:

  • Lazy loading , uno dei modi più efficaci per prevenire gli errori dell'ordine di inizializzazione.
  • Notifiche di modifica , che sono praticamente l'intera base per l' architettura MVVM .
  • L'ereditarietà , ad esempio la definizione di classi astratte Typeo Namederivate, può fornire metadati interessanti ma costanti su se stesse.
  • Intercettazione , grazie a quanto sopra.
  • Gli indicizzatori , che chiunque abbia mai dovuto lavorare con l'interoperabilità COM e l'inevitabile quantità di Item(i)chiamate riconoscerà come una cosa meravigliosa.
  • Lavora con PropertyDescriptor, essenziale per la creazione di designer e per i framework XAML in generale.

Richter è chiaramente un autore prolifico e sa molto su CLR e C #, ma devo dire che sembra che quando originariamente scrisse questo consiglio (non sono sicuro che sia nelle sue revisioni più recenti - spero sinceramente di no) che semplicemente non voleva abbandonare le vecchie abitudini e aveva problemi ad accettare le convenzioni del C # (rispetto al C ++, ad esempio).

Ciò che intendo con questo è che il suo argomento "proprietà considerate dannose" si riduce essenzialmente a una singola affermazione: le proprietà sembrano campi, ma potrebbero non agire come campi. E il problema con l'affermazione è che non è vero o, nella migliore delle ipotesi, è altamente fuorviante. Le proprietà non sembrano campi - almeno, non dovrebbero apparire come campi.

Ci sono due convenzioni di codifica molto forti in C # con convenzioni simili condivise da altri linguaggi CLR e FXCop ti urlerà contro se non le segui:

  1. I campi dovrebbero essere sempre privati, mai pubblici.
  2. I campi devono essere dichiarati in camelCase. Le proprietà sono PascalCase.

Pertanto, non vi è ambiguità sul fatto che Foo.Bar = 42sia una funzione di accesso alla proprietà o una funzione di accesso al campo. È una funzione di accesso di proprietà e dovrebbe essere trattato come qualsiasi altro metodo: potrebbe essere lento, potrebbe generare un'eccezione, ecc. Questa è la natura di Abstraction : dipende interamente dalla discrezione della classe dichiarante come reagire. I progettisti di classi dovrebbero applicare il principio della minima sorpresa, ma i chiamanti non dovrebbero dare per scontato nulla su una proprietà tranne che fa quello che dice sulla scatola. È apposta.

L'alternativa alle proprietà sono i metodi getter / setter ovunque. Questo è l'approccio Java, ed è stato controverso sin dall'inizio . Va bene se questo è il tuo bagaglio, ma non è il modo in cui entriamo nel campo .NET. Cerchiamo, almeno entro i confini di un sistema tipizzato staticamente, di evitare quello che Fowler chiama rumore sintattico . Non vogliamo parentesi extra, extra get/ setverruche o firme di metodi extra - non se possiamo evitarli senza alcuna perdita di chiarezza.

Dì quello che vuoi, ma foo.Bar.Baz = quux.Answers[42]sarà sempre molto più facile da leggere di foo.getBar().setBaz(quux.getAnswers().getItem(42)). E quando leggi migliaia di righe di questo al giorno, fa la differenza.

(E se la tua risposta naturale al paragrafo precedente è di dire "certo è difficile da leggere, ma sarebbe più facile se lo dividi in più righe", allora mi dispiace dire che hai completamente perso il punto .)


11

Non vedo alcun motivo per cui non dovresti usare Proprietà in generale.

Le proprietà automatiche in C # 3+ semplificano solo un po 'la sintassi (a la sintassi).


per favore, leggi le pagine 215-216 in quel libro. Sono sicuro che sai chi è Jeffrey Richter!
Quan Mai,

Ho letto (CLR tramite C #, 2a Ed.), Non sono d'accordo con la sua posizione e non vedo ragioni reali per non usare le proprietà!
abatishchev

È un buon libro, ma in questo momento non sono d'accordo con l'autore.
Konstantin Tarkus

Dov'è esattamente quel posto in cui l'autore suggerisce di non utilizzare Proprietà? Non ho trovato nulla a p.215-217
Konstantin Tarkus,

Ho aggiunto le opinioni di Jeffrey nella mia domanda :). Puoi trovarlo alle pagine 215-216 in edizione cartacea :)
Quan Mai

9

È solo l'opinione di una persona. Ho letto parecchi libri c # e non ho ancora visto nessun altro che dice "non usare le proprietà".

Personalmente penso che le proprietà siano una delle cose migliori di c #. Ti permettono di esporre lo stato tramite qualsiasi meccanismo tu voglia. Puoi pigramente istanziare la prima volta che qualcosa viene usato e puoi fare la convalida sull'impostazione di un valore, ecc. Quando li usi e li scrivi, penso alle proprietà come setter e getter che hanno una sintassi molto più carina.

Per quanto riguarda le avvertenze con le proprietà, ce ne sono un paio. Uno è probabilmente un uso improprio delle proprietà, l'altro può essere sottile.

In primo luogo, le proprietà sono tipi di metodi. Può essere sorprendente se si inserisce una logica complicata in una proprietà perché la maggior parte degli utenti di una classe si aspetterà che la proprietà sia abbastanza leggera.

Per esempio

public class WorkerUsingMethod
{
   // Explicitly obvious that calculation is being done here
   public int CalculateResult()
   { 
      return ExpensiveLongRunningCalculation();
   }
}

public class WorkerUsingProperty
{
   // Not at all obvious.  Looks like it may just be returning a cached result.
   public int Result
   {
       get { return ExpensiveLongRunningCalculation(); }
   }
}

Trovo che l'utilizzo di metodi per questi casi aiuti a fare una distinzione.

In secondo luogo, e soprattutto, le proprietà possono avere effetti collaterali se vengono valutate durante il debug.

Supponi di avere una proprietà come questa:

public int Result 
{ 
   get 
   { 
       m_numberQueries++; 
       return m_result; 
   } 
}

Supponiamo ora di avere un'eccezione che si verifica quando vengono effettuate troppe query. Indovina cosa succede quando avvii il debug e rollover la proprietà nel debugger? Cose brutte. Evita di farlo! Guardando la proprietà cambia lo stato del programma.

Questi sono gli unici avvertimenti che ho. Penso che i vantaggi delle proprietà superino di gran lunga i problemi.


6

Questo motivo deve essere stato fornito in un contesto molto specifico. Di solito è il contrario: si consiglia di utilizzare le proprietà in quanto ti danno un livello di astrazione che ti consente di cambiare il comportamento di una classe senza influenzare i suoi clienti ...


+1 per evidenziare implicitamente l'importanza del "contratto" tra il cliente e la proprietà della classe.
TheBlastOne

6

Non posso fare a meno di scegliere i dettagli delle opinioni di Jeffrey Richter:

Una proprietà può essere di sola lettura o di sola scrittura; l'accesso al campo è sempre leggibile e scrivibile.

Sbagliato: i campi possono essere contrassegnati come di sola lettura, quindi solo il costruttore dell'oggetto può scrivere su di essi.

Un metodo di proprietà può generare un'eccezione; l'accesso al campo non genera mai un'eccezione.

Sbagliato: l'implementazione di una classe può cambiare il modificatore di accesso di un campo da pubblico a privato. I tentativi di leggere i campi privati ​​in fase di esecuzione risulteranno sempre in un'eccezione.


5

Non sono d'accordo con Jeffrey Richter, ma posso immaginare perché non gli piacciono le proprietà (non ho letto il suo libro).

Anche se le proprietà sono proprio come i metodi (per quanto riguarda l'implementazione), come utente di una classe, mi aspetto che le sue proprietà si comportino "più o meno" come un campo pubblico, ad esempio:

  • non ci sono operazioni che richiedono tempo in corso all'interno della proprietà getter / setter
  • il property getter non ha effetti collaterali (chiamandolo più volte, non cambia il risultato)

Sfortunatamente, ho visto proprietà che non si sono comportate in questo modo. Ma il problema non sono le proprietà stesse, ma le persone che le hanno implementate. Quindi richiede solo un po 'di educazione.


1
+1 poiché sottolinea l'importanza di un contratto pulito. Avere una proprietà apparentemente di sola lettura che restituisce regolarmente un valore diverso su ogni riferimento è una proprietà di lettura e scrittura: semplicemente non scrive sul proprio valore, ma su altre variabili di istanza (direttamente o indirettamente). Non è un cattivo stile, ma deve essere documentato (o essere una parte implicita del contratto).
TheBlastOne

4

C'è un momento in cui prendo in considerazione di non utilizzare le proprietà, e questo è nella scrittura del codice .Net Compact Framework. Il compilatore CF JIT non esegue la stessa ottimizzazione del compilatore JIT desktop e non ottimizza le funzioni di accesso alle proprietà semplici, quindi in questo caso l'aggiunta di una proprietà semplice causa un piccolo sovraccarico di codice utilizzando un campo pubblico. Di solito questo non sarebbe un problema, ma quasi sempre nel mondo Compact Framework ti trovi di fronte a stretti vincoli di memoria, quindi anche piccoli risparmi come questo contano.


4

Non dovresti evitare di usarli ma dovresti usarli con qualificazione e cura, per le ragioni fornite da altri collaboratori.

Una volta ho visto una proprietà chiamata qualcosa come Clienti che ha aperto internamente una chiamata out-of-process a un database e ha letto l'elenco dei clienti. Il codice client aveva un 'for (int i to Customers.Count)' che causava una chiamata separata al database ad ogni iterazione e per l'accesso del cliente selezionato. Questo è un esempio eclatante che dimostra il principio di mantenere la proprietà molto leggera, raramente più di un accesso interno al campo.

Un argomento per l'utilizzo delle proprietà è che consentono di convalidare il valore impostato. Un altro è che il valore della proprietà può essere un valore derivato, non un singolo campo, come TotalValue = importo * quantità.


3

Personalmente utilizzo le proprietà solo quando creo semplici metodi get / set. Mi allontano da esso quando arrivo a strutture di dati complicate.


3

L'argomento presume che le proprietà siano cattive perché sembrano campi, ma può eseguire azioni sorprendenti. Questa ipotesi è invalidata dalle aspettative dei programmatori .NET:

Le proprietà non sembrano campi. I campi sembrano proprietà.

• Un metodo di proprietà può generare un'eccezione; l'accesso al campo non genera mai un'eccezione.

Quindi, un campo è come una proprietà a cui è garantito che non genererà mai un'eccezione.

• Una proprietà non può essere passata come parametro out o ref a un metodo; un campo può.

Quindi, un campo è come una proprietà, ma ha funzionalità aggiuntive: passare a un ref/ outaccettare metodi.

• L'esecuzione di un metodo di proprietà può richiedere molto tempo; l'accesso al campo viene sempre completato immediatamente. [...]

Quindi, un campo è come una proprietà veloce.

• Se chiamato più volte di seguito, un metodo di proprietà può restituire ogni volta un valore diverso; un campo restituisce ogni volta lo stesso valore. La classe System.DateTime ha una proprietà Now di sola lettura che restituisce la data e l'ora correnti.

Pertanto, un campo è come una proprietà a cui è garantito di restituire lo stesso valore a meno che il campo non sia stato impostato su un valore diverso.

• Un metodo di proprietà può causare effetti collaterali osservabili; l'accesso al campo non lo fa mai.

Anche in questo caso, un campo è una proprietà a cui è garantito che non lo farà.

• Un metodo di proprietà può richiedere memoria aggiuntiva o restituire un riferimento a qualcosa che non fa effettivamente parte dello stato dell'oggetto, quindi la modifica dell'oggetto restituito non ha alcun effetto sull'oggetto originale; l'interrogazione di un campo restituisce sempre un riferimento a un oggetto che è garantito essere parte dello stato dell'oggetto originale. Lavorare con una proprietà che restituisce una copia può creare confusione per gli sviluppatori e questa caratteristica spesso non è documentata.

Questo può essere sorprendente, ma non perché è una proprietà che fa questo. Piuttosto, è che a malapena qualcuno restituisce copie modificabili nelle proprietà, quindi il caso dello 0,1% è sorprendente.


0

Il richiamo di metodi anziché di proprietà riduce notevolmente la leggibilità del codice di invocazione. In J #, ad esempio, l'utilizzo di ADO.NET era un incubo perché Java non supporta proprietà e indicizzatori (che sono essenzialmente proprietà con argomenti). Il codice risultante era estremamente brutto, con chiamate di metodi tra parentesi vuote ovunque.

Il supporto per proprietà e indicizzatori è uno dei vantaggi di base di C # rispetto a Java.

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.