Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Annotazioni
Questo contenuto viene ristampato con il permesso di Pearson Education, Inc. da Framework Design Guidelines: Conventions, Idioms e Pattern per Librerie .NET Riutilizzabili, 2a Edizione. Tale edizione è stata pubblicata nel 2008 e il libro è stato completamente rivisto nella terza edizione. Alcune informazioni in questa pagina potrebbero non essere aggiornate.
Una delle decisioni di progettazione fondamentali che ogni progettista di framework deve affrontare è se progettare un tipo come classe (un tipo di riferimento) o come struct (un tipo valore). Una buona comprensione delle differenze nel comportamento dei tipi di riferimento e dei tipi valore è fondamentale per effettuare questa scelta.
La prima differenza tra tipi di riferimento e tipi di valore da considerare è che i tipi di riferimento vengono allocati nell'heap e raccolti dal Garbage Collector, mentre i tipi di valore vengono allocati nello stack o inline nei tipi che li contengono e deallocati quando lo stack si esaurisce o quando il loro tipo contenitore viene deallocato. Di conseguenza, le allocazioni e le deallocazioni dei tipi di valore sono in generale più economiche rispetto alle allocazioni e deallocazioni dei tipi di riferimento.
Successivamente, le matrici di tipi riferimento vengono allocate all'esterno della riga, il che significa che gli elementi della matrice sono solo riferimenti alle istanze del tipo di riferimento che si trovano nell'heap. Le matrici di tipi valore vengono allocate inline, ovvero gli elementi della matrice sono le istanze effettive del tipo valore. Di conseguenza, le allocazioni e le deallocazione delle matrici di tipi di valore sono molto più economiche rispetto alle allocazioni e deallocazione delle matrici di tipi di riferimento. Inoltre, nella maggior parte dei casi le matrici di tipi valore presentano una località di riferimento notevolmente migliore.
La differenza successiva è correlata all'utilizzo della memoria. I tipi valore vengono convertiti in tipi di riferimento quando viene eseguito il cast a un tipo di riferimento o a una delle interfacce che implementano. Vengono liberati dal box quando vengono convertiti di nuovo al tipo di valore. Poiché gli oggetti 'box' sono allocati nell'heap e sono soggetti a garbage collection, un eccesso di operazioni di boxing e unboxing può avere un impatto negativo sull'heap, sul garbage collector e infine sulle prestazioni dell'applicazione. Al contrario, tale boxing non si verifica quando vengono cast dei tipi di riferimento. Per altre informazioni, vedere Boxing e Unboxing.
Successivamente, le assegnazioni dei tipi di riferimento copiano il riferimento, mentre le assegnazioni di tipo valore copiano l'intero valore. Di conseguenza, le assegnazioni di tipi riferimento di grandi dimensioni sono più economiche rispetto alle assegnazioni di tipi valore di grandi dimensioni.
Infine, i tipi di riferimento vengono passati tramite riferimento, mentre i tipi di valore vengono passati tramite valore. Le modifiche apportate a un'istanza di un tipo di riferimento influiscono su tutti i riferimenti che puntano all'istanza. Le istanze del tipo di valore vengono copiate quando vengono passate per valore. Quando viene modificata un'istanza di un tipo valore, naturalmente non influisce su nessuna delle sue copie. Poiché le copie non vengono create in modo esplicito dall'utente, ma vengono create in modo implicito quando vengono passati argomenti o vengono restituiti valori di ritorno, i tipi di valore che possono essere modificati possono generare confusione in molti utenti. Pertanto, i tipi valore devono essere non modificabili.
Come regola generale, la maggior parte dei tipi in un framework deve essere classi. Esistono tuttavia alcune situazioni in cui le caratteristiche di un tipo valore rendono più appropriato usare gli struct.
✔️ CONSIDERARE la definizione di uno struct invece di una classe se le istanze del tipo sono di piccole dimensioni e comunemente di breve durata o sono comunemente incorporate in altri oggetti.
❌ EVITARE di definire uno struct a meno che il tipo non abbia tutte le caratteristiche seguenti:
Rappresenta logicamente un singolo valore, simile ai tipi primitivi (
int
,double
e così via).Ha una dimensione dell'istanza inferiore a 16 byte.
Non è modificabile.
Non dovrà essere sottoposto a boxing frequentemente.
In tutti gli altri casi, è necessario definire i tipi come classi.
© Porzioni 2005, 2009 Microsoft Corporation. Tutti i diritti riservati.
Ristampato dall'autorizzazione di Pearson Education, Inc. da Framework Design Guidelines: Conventions, Idioms e Patterns for Reusable .NET Libraries, 2nd Edition di Krzysztof Cwalina e Brad Abrams, pubblicato il 22 ottobre 2008 da Addison-Wesley Professional come parte della Serie di sviluppo di Microsoft Windows.