Procedura dettagliata: modifica di un componente con Visual C#
I componenti forniscono codice riutilizzabile sotto forma di oggetti. Un'applicazione che utilizza il codice di un componente, tramite la creazione di oggetti e la chiamata ai relativi metodi e proprietà, viene definita client. Un client può trovarsi o meno nello stesso assembly del componente da esso utilizzato.
Ogni procedura riportata di seguito viene compilata sulla base delle procedure precedenti, pertanto l'ordine in cui vengono eseguite è importante.
Nota
È possibile che le finestre di dialogo e i comandi di menu visualizzati siano diversi da quelli descritti nella Guida a seconda delle impostazioni attive o dell'edizione del programma. Per modificare le impostazioni, scegliere Importa/Esporta impostazioni dal menu Strumenti. Per ulteriori informazioni, vedere Gestione delle impostazioni.
Creazione del progetto
Per creare la libreria di classi CDemoLib e il componente CDemo
Scegliere Nuovo dal menu File, quindi fare clic su Progetto. Verrà visualizzata la finestra di dialogo Nuovo progetto. Selezionare il modello di progetto Libreria di classi dall'elenco dei progetti di Visual C#, quindi immettere CDemoLib nella casella Nome.
Nota
Quando si crea un nuovo progetto, specificarne sempre il nome. Questa operazione consente di impostare lo spazio dei nomi di primo livello, il nome dell'assembly e il nome del progetto e garantisce che il componente predefinito venga inserito nello spazio dei nomi corretto.
In Esplora soluzioni fare clic con il pulsante destro del mouse su CDemoLib e scegliere Proprietà dal menu di scelta rapida. La casella Spazio dei nomi predefinito contiene CDemoLib.
Lo spazio dei nomi di primo livello viene utilizzato per qualificare i nomi dei componenti dell'assembly. Se ad esempio due assembly forniscono componenti denominati CDemo, sarà possibile specificare il componente CDemo utilizzando CDemoLib.CDemo.
Chiudere la finestra di dialogo.
Scegliere Aggiungi componente dal menu Progetto.
Nella finestra di dialogo Aggiungi nuovo elemento selezionare Classe Component e digitare CDemo.cs nella casella Nome. Fare clic su Aggiungi per creare il componente.
Alla libreria di classi verrà aggiunto un componente denominato CDemo.
In Esplora soluzioni fare clic con il pulsante destro del mouse su CDemo.cs e scegliere Visualizza codice dal menu di scelta rapida. Verrà aperto l'editor del codice.
Si noti l'oggetto : Component immediatamente sotto public partial class CDemo. Questa sezione designa la classe da cui eredita la classe in uso. Per impostazione predefinita, un componente eredita dalla classe Component fornita dal sistema. La classe Component fornisce diverse funzionalità per i componenti, compresa la possibilità di utilizzare le finestre di progettazione.
In Esplora soluzioni fare clic con il pulsante destro del mouse su Class1.cs e scegliere Elimina. Verrà in tal modo eliminata la classe predefinita fornita con la libreria di classi, che non verrà utilizzata in questa procedura dettagliata.
Per salvare il progetto, scegliere Salva tutto dal menu File.
Aggiunta di costruttori e distruttori
I costruttori controllano l'inizializzazione del componente, mentre il metodo Finalize ne controlla la chiusura. Il codice nel costruttore e il metodo Finalize della classe CDemo mantengono un conteggio parziale degli oggetti CDemo esistenti.
Per aggiungere codice per il costruttore e il distruttore della classe CDemo
Nell'editor di codice aggiungere variabili membro per gestire un totale parziale delle istanze della classe CDemo e un numero ID per ciascuna istanza.
public readonly int InstanceID; private static int NextInstanceID = 0; private static long ClassInstanceCount = 0;
Le variabili membro InstanceCount e NextInstanceID sono dichiarate static e pertanto esistono solo a livello di classe. Tutte le istanze di CDemo che accedono a questi membri utilizzano le stesse aree di memoria. L'inizializzazione dei membri statici viene eseguita alla prima ricorrenza del riferimento alla classe CDemo nel codice, ovvero la prima volta in cui viene creato un oggetto CDemo o in cui viene eseguito l'accesso a uno dei membri statici della classe.
Individuare public CDemo() e public CDemo(IContainer container), i costruttori predefiniti della classe CDemo. In Visual C# tutti i costruttori hanno lo stesso nome della classe. Il componente può contenere diversi costruttori, con parametri differenti, ma devono tutti avere lo stesso nome del componente.
Nota
Il livello di accesso dei costruttori determina quali client potranno creare istanze della classe.
Aggiungere il codice riportato di seguito a public CDemo() per incrementare il conteggio delle istanze quando si crea un nuovo oggetto CDemo e per impostare il numero di ID dell'istanza.
Nota
Aggiungere il codice sempre dopo la chiamata a InitializeComponent. A questo punto, tutti i componenti costitutivi saranno stati inizializzati.
InstanceID = NextInstanceID ++; ClassInstanceCount ++;
In quanto membro readonly , InstanceID può essere impostato solo nel costruttore .
Nota
Gli utenti che hanno familiarità con il multithreading sapranno che l'assegnazione di InstanceID e l'incremento di NextInstanceID sono operazioni estremamente specifiche e delicate. Queste e altre problematiche correlate al threading sono illustrate nella sezione Procedura dettagliata: modifica di componenti multithreading semplici con Visual C#.
Alla fine del costruttore aggiungere il seguente metodo:
~CDemo() { ClassInstanceCount --; }
Questo metodo è definito distruttore e viene indicato mediante il carattere tilde (~) davanti al nome della classe. Il gestore di memoria chiama il distruttore prima di recuperare la memoria occupata dall'oggetto CDemo. Se si implementa un distruttore sarà possibile effettuare le operazioni di pulitura immediatamente prima della rimozione del componente dalla memoria. Tuttavia, come riportato più avanti in questa procedura dettagliata, per diversi motivi è consigliabile rilasciare anticipatamente le risorse.
Aggiunta di una proprietà alla classe
La classe CDemo contiene una singola proprietà, una proprietà statica che consente al client di verificare il numero di oggetti CDemo presenti in memoria in un determinato momento. Le modalità di creazione dei metodi sono analoghe a quelle per la creazione delle proprietà.
Per creare una proprietà per la classe CDemo
Aggiungere alla classe CDemo la seguente dichiarazione di proprietà per consentire ai client di recuperare il numero delle istanze di CDemo.
public static long InstanceCount { get { return ClassInstanceCount; } }
Test del componente
Per eseguire il test del componente è necessario un progetto in cui venga utilizzato il componente. Questo progetto deve essere il primo progetto che si avvia quando si fa clic sul pulsante Esegui.
Per aggiungere il progetto client CDemoTest come progetto di avvio per la soluzione
Scegliere Aggiungi dal menu File, quindi fare clic su Nuovo progetto. Verrà visualizzata la finestra di dialogo Aggiungi nuovo progetto.
Selezionare il modello di progetto Applicazione Windows, digitare CDemoTest nella casella Nome e quindi scegliere OK.
In Esplora soluzioni fare clic con il pulsante destro del mouse su CDemoTest, quindi scegliere Imposta come progetto di avvio dal menu di scelta rapida.
Per utilizzare il componente CDemo è necessario che il progetto client di test contenga un riferimento al progetto della libreria di classi. Una volta aggiunto il riferimento, si consiglia di aggiungere un'istruzione using all'applicazione di test per semplificare l'utilizzo del componente.
Per aggiungere un riferimento al progetto della libreria di classi
In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo Riferimenti immediatamente sotto CDemoTest, quindi scegliere Aggiungi riferimento dal menu di scelta rapida.
Nella finestra di dialogo Aggiungi riferimento fare clic sulla scheda Progetti.
Fare doppio clic sul progetto di libreria di classi CDemoLib. CDemoLib verrà visualizzato sotto il nodo Riferimenti del progetto CDemoTest.
In Esplora soluzioni fare clic con il pulsante destro del mouse su Form1.cs e scegliere Visualizza codice dal menu di scelta rapida.
L'aggiunta del riferimento a CDemoLib consente di utilizzare il nome completo del componente CDemo ovvero CDemoLib.CDemo.
Per aggiungere un'istruzione using
Aggiungere la seguente istruzione using all'elenco delle istruzioni using nella parte superiore dell'editor di codice per Form1.
using CDemoLib;
L'aggiunta dell'istruzione using consente di omettere il nome della libreria e di fare riferimento al tipo del componente come CDemo.
A questo punto, per eseguire il test del componente, è necessario creare e utilizzare un programma di test.
Informazioni sulla durata degli oggetti
Il programma CDemoTest illustrerà la durata degli oggetti in .NET Framework mediante la creazione e il rilascio di un numero elevato di oggetti CDemo.
Per aggiungere il codice per la creazione e il rilascio degli oggetti CDemo
Fare clic su Form1.cs[Design] per tornare alla finestra di progettazione.
Trascinare un oggetto Button e un oggetto Timer dalla scheda Tutti i Windows Form della Casella degli strumenti all'area di progettazione di Form1.
Il componente Timer non visivo verrà visualizzato in un'area di progettazione distinta sotto il form.
Fare doppio clic sull'icona di timer1 per creare un metodo di gestione degli eventi per l'evento Tick del componente Timer1. Inserire nel metodo di gestione degli eventi il seguente codice.
this.Text = "CDemo instances: " + CDemo.InstanceCount;
A ogni scatto del timer, nella didascalia del form verrà visualizzato il conteggio corrente delle istanze della classe CDemo. Il nome della classe viene utilizzato come qualificatore per la proprietà statica InstanceCount. Non è necessario creare un'istanza di CDemo per accedere a un membro statico.
Individuare il costruttore per Form1 (public Form1()) e, dopo la chiamata a InitializeComponent(), aggiungere il seguente codice:
timer1.Enabled = true;
Il timer verrà avviato non appena viene creato il form.
Fare clic sulla scheda Form1.vb [Design] per tornare alla finestra di progettazione.
Fare doppio clic su Button in Form1 per creare un metodo di gestione degli eventi per l'evento Click del pulsante. Inserire nel metodo di gestione degli eventi il seguente codice.
CDemo cd; int ct; for (ct = 0; ct < 1000; ct++) cd = new CDemo();
Questo codice potrebbe apparire strano. Via via che viene creata una nuova istanza di CDemo, viene rilasciata l'istanza precedente. Al termine del ciclo for, rimarrà una sola istanza di CDemo. Quando il metodo di gestione degli eventi termina, anche l'unica istanza rimasta verrà rilasciata, in quanto la variabile cd non rientra più nell'ambito di validità.
Come forse si sarà già intuito, le cose non vanno proprio così.
Per eseguire e sottoporre a debug i progetti CDemoTest e CDemo
Premere F5 per avviare la soluzione.
Il progetto client verrà avviato e verrà visualizzato Form1. Tenere presente che nella didascalia del form viene visualizzato "CDemo instances: 0".
Fare clic sul pulsante. Nella didascalia del form verrà visualizzato "CDemo instances: 1000".
Tutte le istanze di CDemo sono state rilasciate entro il termine della routine di gestione dell'evento Click del pulsante. Di seguito viene illustrato il motivo per cui le istanze non sono state completate. In breve, il gestore di memoria completa gli oggetti in background, a bassa priorità. La priorità viene aumentata solo se la memoria disponibile nel sistema è insufficiente. Questa lentezza della procedura di Garbage Collection consente un'allocazione degli oggetti estremamente rapida.
Fare clic sul pulsante più volte e osservare la didascalia. A un certo punto il numero delle istanze subirà un'improvvisa diminuzione. Ciò indica che il gestore di memoria ha recuperato la memoria di alcuni oggetti.
Nota
Se si è fatto clic più di 10 volte e il numero delle istanze di CDemo non è diminuito, potrebbe essere necessario modificare il codice in modo da utilizzare una maggiore quantità di memoria. Chiudere il form per tornare all'ambiente di sviluppo e portare a 10000 il numero di iterazioni nel ciclo for. Ripetere quindi l'esecuzione del progetto.
Ripetere il passaggio 3. Verrà allocato un maggior numero di oggetti prima che il gestore di memoria completi altri oggetti.
Infatti, ogni volta che si ripete il passaggio 3, probabilmente sarà possibile allocare più oggetti CDemo prima che il gestore della memoria intervenga. Questo perché una parte sempre maggiore di Visual Studio viene scambiata, lasciando più spazio per le istanze di CDemo.
Chiudere il form per tornare all'ambiente di sviluppo.