Oppure

Loading
02/08/11 10:28
BionicGod
1° QUESITO
E' vero che le strutture si prediligono per gestire minori quantità di dati, invece le classi per maggiori quantità per via del loro modo di archiviare informazioni (value e reference)?
2°QUESITO
Se da una classe creo un oggetto, lo utilizzo per poco e poi non mi serve più come lo distruggo per liberare memoria?
Penso che devo utilizzare un distruttore
~Oggetto()
        {
        }

Ma cosa dovrei scriverci dentro? Non ho per niente chiaro come liberare memoria.
Non c'è il metodo Dispose(), neanche Finalize(). In genere io chiudo e faccio Dispose() su tutte le variabili (sulle quali si può fare) dell'oggetto, ma la classe?
aaa
02/08/11 11:58
Phil93
Le strutture sono tipi valore, pertanto vengono allocate nello Stack e vengono liberate dalla memoria non appena escono dallo scope (ambito di visibilità;). Sono utilizzate prevalentemente per tipi numerici e dati comunque di piccole dimensioni. I tipi numerici di .NET infatti sono strutture, così come i tipi nullable (strutture generiche).

Le classi invece sono tipi reference e le istanze sono allocate nel managed heap. Si chiama managed perchè, a differenza di C++ ad esempio, la memoria è gestita autonomamente dal CLR e in particolare dal Garbage Collector, che si occupa da solo di eliminare gli oggetti non più referenziati. (Ah, ovviamente un'istanza di classe può avere più variabili che la referenziano). Quindi, a differenza di C++ non è possibile eliminare esplicitamente un oggetto, poichè esso potrebbe essere referenziato ancora in un'altra parte del programma. Quello che puoi fare è agire sulla classe GC, che è un astrazione del Garbage Collector e permette di controllarlo a runtime. Un metodo esposto da GC è per esempio Collect(), che forza il garbage collector ad analizzare la memoria e liberare gli oggetti non referenziati. Per informazioni ulteriori ti rimando all'articolo sulla classe GC di MSDN.

Le differenze tra strutture e classi sono altre comunque. Ad esempio, tutte e due possono implementare interfacce, ma le strutture non ereditano. Inoltre, il costrutture senza parametri delle strutture è riservato e serve a inizializzare i campi al valore di default.

Dispose e Finalize sono cose un po' diverse, dato che servono a far liberare all'istanza le risorse esterne (unmanaged) che ha utilizzato, e non l'istanza stessa.
Le differenze sono che Dispose è un metodo esposto dall'interfaccia IDisposable, mentre Finalize è un metodo virtuale della classe object. Inoltre, Dispose è fatto apposta per far si che l'utente che utilizza la classe possa liberare le risorse unmanaged in qualsiasi momento, richiamando il metodo, mentre Finalize è richiamato SOLO dal garbage collector quando, e solo quando, l'oggetto sta per essere cancellato dalla memoria.

Di solito Finalize e Dispose vengono implementati insieme, in modo che se l'utente non ha liberato le risorse esterne manualmente tramite Dispose, se ne occupa il GC invocando Finalize.

In risposta, quindi, al secondo quesito posso dire che quello che puoi fare e stare tranquillo e lasciare che il Garbage Collector faccia il suo dovere. Se proprio vuoi metterci le mani, puoi usare GC.Collect(), che è sovraccaricato in modo da accettare varie modalità e specifiche generazioni di oggetti da esaminare (se non sai cosa cono le generazioni ti rimando a articoli più specifici riguardo alla gestione della memoria in .NET).

Spero di essere stato abbastanza chiaro..
Ultima modifica effettuata da Phil93 02/08/11 12:07
aaa
02/08/11 12:01
nessuno
Aggiungo che non è buona norma forzare il Garbage Collector.

E' sempre meglio lasciar fare all'engine che sa quando e come liberare la memoria dai dati non utilizzati.
Ricorda che nessuno è obbligato a risponderti e che nessuno è perfetto ...
---
Il grande studioso italiano Bruno de Finetti ( uno dei padri fondatori del moderno Calcolo delle probabilità ) chiamava il gioco del Lotto Tassa sulla stupidità.
02/08/11 12:14
Phil93
Esatto, anche perchè tra le altre cose la garbage collection determina un (seppur minimo) overhead nel tempo di esecuzione, quindi la cosa megliore è mettersi il cuore in pace e far fare al CLR quello che ben sa fare...
aaa
02/08/11 19:15
Il Totem
Inoltre, a livello di ingegneria del software, le strutture si utilizzano per esporre dati, mentre le classi per esporre funzionalità (e in genere nascondono i dati). Non è quindi detto che grandi quantità di dati implichino l'uso di una classe: anzi, sarebbe più consono pensare a una struttura.

Per quanto riguarda la liberazione di memoria, Dispose e Finalize devono essere ridefinite, come già detto, per liberare risorse non gestite. Ogni risorsa gestita (memoria compresa) viene liberata automaticamente dal GC quando è possibile o necessario farlo. Se non sai cosa scrivere nel distruttore, allora non scrivere nulla, poiché significa che non ci sono oggetti unmanaged che devi gestire.
aaa