Condividi tramite


Inizializzazione e terminazione di componenti

Il componente viene inizializzato dal relativo costruttore (SubNew in Visual Basic) e viene eliminato dal relativo distruttore (SubFinalizein Visual Basic). Il costruttore del componente viene chiamato durante, e non dopo, la creazione di un'istanza del componente. Il distruttore viene chiamato immediatamente prima della distruzione del componente mediante la procedura di Garbage Collection e del recupero della relativa memoria.

Nota di Visual BasicNota di Visual Basic

Nelle versioni precedenti di Visual Basic le funzioni degli eventi Initialize e Terminate erano identiche a quelle del costruttore e del distruttore.

Attesa della procedura di Garbage Collection

Common Language Runtime chiama il distruttore del componente dopo che la procedura di Garbage Collection determina che non è più possibile raggiungere il componente mediante l'esecuzione del codice. Questa situazione si verifica nel caso in cui tutti i riferimenti al componente siano stati rilasciati o se gli unici riferimenti al componente sono contenuti negli oggetti che a loro volta risultano non raggiungibili mediante l'esecuzione del codice, come nel caso dei riferimenti circolari.

Poiché è possibile che si verifichi un ritardo tra il momento in cui il componente non è più utilizzato dall'utente e il momento in cui viene chiamato il distruttore del componente, nella durata dei componenti .NET Framework viene introdotto un ulteriore passaggio: se il componente acquisisce risorse di sistema, quali connessioni a database o handle a oggetti del sistema Windows, sarà necessario implementare l'interfaccia IDisposable e fornire un metodo Dispose in modo da consentire agli utenti del componente di scegliere il momento in cui rilasciare le risorse.

Ciclo di vita di un componente

Inizializzazione del tipo: quando si crea la prima istanza del componente, la prima parte di codice eseguita è rappresentata da eventuali inizializzazioni condivise. Anche un riferimento a un eventuale membro condiviso comporta l'esecuzione del costruttore condiviso. In tale riferimento sono inclusi tutti i campi condivisi (variabili membro) inizializzati e, se presente, il costruttore condiviso (Shared Sub New). Nel codice riportato di seguito viene creato un tipo di carattere di riferimento per l'intera classe.

Nota

La parola chiave C# corrispondente a Shared è static, che non deve essere confusa con la parola chiave Static di Visual Basic.

Public Class ADrawing
Shared ReadOnly ReferenceFont As New Font("TimesNewRoman", 14)
' Shared constructor does not overload other constructors.
Shared Sub New()
   ' There is no call to the base class's shared constructor.
   ' Insert code to initialize the shared data.
End Sub
End Class
class ADrawing
{
   static Font m_referenceFont = new Font("TimesNewRoman", 14);
   // Simply add the static keyword to create a static constructor.
   // Static constructors do not have any parameters.
   static ADrawing()
   {
      // There is no call to the base class's static constructor.
      // Code to initialize the font here.
   }
}

Nota

L'inizializzazione della classe può verificarsi anche se non viene creata alcuna istanza del componente.Verrà inizializzata ad esempio una classe abstract (MustInherit) con funzioni membro condivise e tali funzioni potranno essere utilizzate dall'applicazione anche se non viene creata alcuna istanza della classe.

  1. Inizializzazione dell'istanza: quando viene creata un'istanza del componente, vengono inizializzati i membri dati che includono il codice di inizializzazione e viene eseguito l'overload del costruttore appropriato. Nel codice seguente viene inizializzato un campo privato e vengono definiti due costruttori, uno da chiamare se non sono presenti parametri e l'altro da chiamare se l'utente specifica i parametri.

    Class AShape
       Private answer As Integer = 42
       Public Sub New()
          ' Call another constructor with default initialization values.
          MyClass.New(System.Drawing.Color.Red, 5280, DefinedSizes.Large)
       End Sub
       Public Overloads Sub New(myColor As Color, myLength As Integer, _
                Size As DefinedSizes)
          ' Insert code to initialize the class.
       End Sub
       ' Defines the DefinedSizes enum
       Public Enum DefinedSizes
          Large
          Small
       End Enum
    End Class
    
    class AShape
    {
       private int m_answer = 42;
       // Forward to another constructor.
       public AShape() 
       : this(System.Drawing.Color.Red, 5280, DefinedSizes.Large)
       {
          // Additional initialization goes here.
       }
    
       public AShape(Color color, int length, DefinedSizes size)
       {
          // Code to initialize the class goes here.
       }
       // Defines the DefinedSizes enum
       public enum DefinedSizes
       {
          Large,
          Small
       }
    }
    
  2. Eliminazione delle risorse: se il componente implementa l'interfaccia IDisposable, deve fornire un metodo Dispose, che il client dovrà chiamare dopo aver utilizzato il componente. Si noti che qualsiasi componente che eredita da Component dispone già di un'implementazione predefinita di Dispose, che può essere sottoposto a override per fornire un codice di pulizia aggiuntivo. Nel metodo Dispose, il componente libera tutte le risorse di sistema che può aver allocato, rilascia i riferimenti ad altri oggetti e rende se stesso inutilizzabile. Possono verificarsi casi in cui il componente deve chiamare il proprio metodo Dispose. Nel codice seguente viene eliminato un oggetto dipendente che dispone di un metodo Dispose.

    ' Assumes that the class implements IDisposable
    Public Sub Dispose() Implements IDisposable.Dispose
       myWidget.Dispose
       myWidget = Nothing
       ' Insert additional code.
    End Sub
    
    // Assumes that the class implements IDisposable
    public void IDisposable.Dispose()
    {
       mywidget.Dispose();
       mywidget = null;
       // Dispose of remaining objects.
    }
    
    

    Dopo aver chiamato Dispose, il client deve rilasciare tutti i riferimenti rimanenti al componente, in modo tale che la procedura di Garbage Collection sia in grado di recuperare la memoria del componente.

  3. Instance destruction: Quando il Garbage Collection rileva che non sono presenti riferimenti rimanenti al componente, il runtime chiama il distruttore del componenteFinalize(in Visual Basic) e libera la memoria. È necessario eseguire l'override del metodo Finalize della classe di base (per Visual Basic) o implementare un distruttore (per Visual C#) per implementare il proprio codice di pulizia, ma includendo sempre una chiamata al distruttore o al metodo Finalize della classe di base.

    Protected Overrides Sub Finalize()
       m_Gadget = Nothing
       m_Gear = Nothing
       MyBase.Finalize()
    End Sub
    
    // In C#, a destructor is used instead of a Finalize method.
    ~ThisClass()
    {
       m_gadget = null;
       m_gear = null;
       // The base class finalizer is called automatically
    }
    

Quando implementare un metodo Dispose

Se il componente eredita da Component, verrà fornita un'implementazione predefinita del metodo Dispose. È possibile eseguire l'override di questa implementazione per fornire del codice di pulizia personalizzato. Se il componente viene compilato mediante la creazione di un'implementazione personalizzata di IComponent, sarà necessario implementare IDisposable per fornire al componente un metodo Dispose.

Il componente necessita di un metodo Dispose nel caso in cui assegni oggetti di sistema, connessioni a database o altre risorse limitate da rilasciare subito dopo l'utilizzo del componente da parte dell'utente.

L'implementazione di un metodo Dispose è necessaria anche nel caso in cui il componente contenga riferimenti ad altri oggetti che dispongono di metodi Dispose.

Perché implementare un metodo Dispose

A seconda dell'attività di sistema, è possibile che un intervallo di tempo imprevisto trascorra tra il momento in cui il componente non viene più utilizzato da un utente e il momento in cui la procedura di Garbage Collection rileva che il codice del componente non è raggiungibile. Se non si fornisce un metodo Dispose, durante questo intervallo il componente continuerà a utilizzare le relative risorse.

Scenario del caso peggiore

Si consideri un componente server che utilizza una connessione a database e non dispone di un metodo Dispose. In un server che dispone di una grande quantità di memoria è possibile creare e rilasciare molte istanze del componente senza influire in modo significativo sulla memoria disponibile. In tal caso, è possibile che i componenti non vengano distrutti mediante la procedura di Garbage Collection per qualche tempo dopo il rilascio dei relativi riferimenti.

È inoltre possibile che tutte le connessioni al database disponibili vengano utilizzate dai componenti rilasciati ma non distrutti. In questo caso, anche se la memoria nel server non fosse insufficiente, il server potrebbe non essere in grado di rispondere alle richieste degli utenti.

Vedere anche

Attività

Procedura: creare e configurare componenti in modalità progettazione

Riferimenti

Dispose

Finalize

Concetti

Caratteristiche delle classi di componenti

Modifiche alle istanze di componenti in Visual Basic