Durata degli oggetti: come creare ed eliminare definitivamente oggetti (Visual Basic)Object Lifetime: How Objects Are Created and Destroyed (Visual Basic)

È stata creata un'istanza di una classe, un oggetto, mediante la parola chiave New.An instance of a class, an object, is created by using the New keyword. Prima di usare i nuovi oggetti per la prima volta, è spesso necessario eseguire attività di inizializzazione.Initialization tasks often must be performed on new objects before they are used. Tra le attività di inizializzazione più comuni vi sono l'apertura dei file, la connessione a un database e la lettura dei valori delle chiavi del Registro di sistema.Common initialization tasks include opening files, connecting to databases, and reading values of registry keys. Visual Basic controlla l'inizializzazione di nuovi oggetti usando routine denominate costruttori (metodi speciali che consentono il controllo dell'inizializzazione).Visual Basic controls the initialization of new objects using procedures called constructors (special methods that allow control over initialization).

Dopo aver abbandona un ambito, un oggetto viene rilasciato da Common Language Runtime (CLR).After an object leaves scope, it is released by the common language runtime (CLR). Visual Basic controlla il rilascio delle risorse di sistema mediante procedure denominate distruttori.Visual Basic controls the release of system resources using procedures called destructors. Sia i costruttori che i distruttori supportano la creazione di librerie di classi prevedibili e affidabili.Together, constructors and destructors support the creation of robust and predictable class libraries.

Uso di costruttori e distruttoriUsing Constructors and Destructors

È possibile usare costruttori e distruttori per controllare la creazione e l'eliminazione di oggetti.Constructors and destructors control the creation and destruction of objects. Le procedure Sub New e Sub Finalize in Visual Basic inizializzare ed eliminare definitivamente oggetti; sostituiscono i metodi Class_Initialize e Class_Terminate usati in Visual Basic 6,0 e versioni precedenti.The Sub New and Sub Finalize procedures in Visual Basic initialize and destroy objects; they replace the Class_Initialize and Class_Terminate methods used in Visual Basic 6.0 and earlier versions.

Sub NewSub New

Il costruttore Sub New può essere eseguito solo una volta dopo la creazione di una classe.The Sub New constructor can run only once when a class is created. Non può essere chiamato in modo esplicito in alcun punto che non sia la prima riga di codice di un altro costruttore, dalla stessa classe o da una classe derivata.It cannot be called explicitly anywhere other than in the first line of code of another constructor from either the same class or from a derived class. Inoltre, il codice nel metodo Sub New viene sempre eseguito prima di qualsiasi altro codice in una classe.Furthermore, the code in the Sub New method always runs before any other code in a class. Visual Basic crea in modo implicito un costruttore di Sub New in fase di esecuzione se non si definisce in modo esplicito una procedura di Sub New per una classe.Visual Basic implicitly creates a Sub New constructor at run time if you do not explicitly define a Sub New procedure for a class.

Per creare un costruttore per una classe, creare una routine denominata Sub New in qualsiasi punto della definizione della classe.To create a constructor for a class, create a procedure named Sub New anywhere in the class definition. Per creare un costruttore con parametri, specificare i nomi e i tipi di dati degli argomenti su Sub New analogamente a come si specificano argomenti per qualsiasi altra routine, come illustrato nel codice seguente:To create a parameterized constructor, specify the names and data types of arguments to Sub New just as you would specify arguments for any other procedure, as in the following code:

Sub New(ByVal s As String)

I costruttori sono spesso in overload, come nell'esempio seguente:Constructors are frequently overloaded, as in the following code:

Sub New(ByVal s As String, i As Integer)

Quando si definisce una classe derivata da un'altra classe, la prima riga di un costruttore deve essere una chiamata al costruttore della classe base, a meno che questa disponga di un costruttore accessibile che non accetta parametri.When you define a class derived from another class, the first line of a constructor must be a call to the constructor of the base class, unless the base class has an accessible constructor that takes no parameters. Una chiamata della classe base che contiene questo costruttore sarebbe ad esempio MyBase.New(s).A call to the base class that contains the above constructor, for example, would be MyBase.New(s). In caso contrario, MyBase.New è facoltativo e il runtime Visual Basic lo chiama in modo implicito.Otherwise, MyBase.New is optional, and the Visual Basic runtime calls it implicitly.

Dopo aver scritto il codice per chiamare il costruttore di un oggetto padre, è possibile aggiungere un codice di inizializzazione alla routine Sub New.After you write the code to call the parent object's constructor, you can add any additional initialization code to the Sub New procedure. Sub New possibile accettare argomenti quando viene chiamato come costruttore con parametri.Sub New can accept arguments when called as a parameterized constructor. Tali parametri vengono passati dalla routine che chiama il costruttore, ad esempio, Dim AnObject As New ThisClass(X).These parameters are passed from the procedure calling the constructor, for example, Dim AnObject As New ThisClass(X).

Sub FinalizeSub Finalize

Prima di rilasciare oggetti, CLR richiede automaticamente al metodo Finalize gli oggetti che definiscono una routine Sub Finalize.Before releasing objects, the CLR automatically calls the Finalize method for objects that define a Sub Finalize procedure. È possibile che il metodo Finalize contenga codice che è necessario eseguire subito prima dell'eliminazione definitiva di un oggetto, ad esempio codice relativo alla chiusura di file e al salvataggio delle informazioni sullo stato.The Finalize method can contain code that needs to execute just before an object is destroyed, such as code for closing files and saving state information. L'esecuzione di Sub Finalize comporta una lieve riduzione delle prestazioni. Si consiglia quindi di definire un metodo Sub Finalize solo quando è necessario rilasciare in modo esplicito gli oggetti.There is a slight performance penalty for executing Sub Finalize, so you should define a Sub Finalize method only when you need to release objects explicitly.

Nota

Il Garbage Collector in CLR non (e non può) eliminare gli oggetti non gestiti, ovvero gli oggetti eseguiti direttamente dal sistema operativo, all'esterno dell'ambiente CLR.The garbage collector in the CLR does not (and cannot) dispose of unmanaged objects, objects that the operating system executes directly, outside the CLR environment. Questo perché i diversi oggetti non gestiti devono essere eliminati in modi differenti.This is because different unmanaged objects must be disposed of in different ways. Le informazioni non sono direttamente associate all'oggetto non gestito e devono quindi essere identificate nella documentazione relativa all'oggetto.That information is not directly associated with the unmanaged object; it must be found in the documentation for the object. Se una classe usa oggetti non gestiti, è necessario eliminarli nel relativo metodo Finalize.A class that uses unmanaged objects must dispose of them in its Finalize method.

Il distruttore Finalize è un metodo protetto che può essere chiamato solo dalla classe a cui appartiene o dalle classi derivate.The Finalize destructor is a protected method that can be called only from the class it belongs to, or from derived classes. Poiché Finalize viene chiamato automaticamente dal sistema quando viene eliminato definitivamente un oggetto, si consiglia di non chiamare Finalize in modo esplicito dall'esterno dell'implementazione Finalize di una classe derivata.The system calls Finalize automatically when an object is destroyed, so you should not explicitly call Finalize from outside of a derived class's Finalize implementation.

A differenza del metodo Class_Terminate che viene eseguito subito dopo aver impostato un oggetto su Nothing, tra l'abbandono dell'ambito da parte di un oggetto e la chiamata del distruttore Finalize da parte di Visual Basic si verifica generalmente un ritardo.Unlike Class_Terminate, which executes as soon as an object is set to nothing, there is usually a delay between when an object loses scope and when Visual Basic calls the Finalize destructor. Visual Basic .NET consente un secondo tipo di distruttore, IDisposable.Dispose, che può essere chiamato in modo esplicito in qualsiasi momento per rilasciare immediatamente le risorse.Visual Basic .NET allows for a second kind of destructor, IDisposable.Dispose, which can be explicitly called at any time to immediately release resources.

Nota

Un distruttore Finalize non deve generare eccezioni, perché queste non possono essere gestite dall'applicazione e possono provocarne l'interruzione.A Finalize destructor should not throw exceptions, because they cannot be handled by the application and can cause the application to terminate.

Uso dei metodi New e Finalize in una gerarchia di classiHow New and Finalize Methods Work in a Class Hierarchy

Ogni volta che viene creata un'istanza di una classe, nel Common Language Runtime (CLR) viene effettuato un tentativo di eseguire una routine denominata New, se esiste in quell'oggetto.Whenever an instance of a class is created, the common language runtime (CLR) attempts to execute a procedure named New, if it exists in that object. New è un tipo di routine denominato constructor utilizzato per inizializzare nuovi oggetti prima dell'esecuzione di qualsiasi altro codice in un oggetto.New is a type of procedure called a constructor that is used to initialize new objects before any other code in an object executes. Un costruttore New consente di aprire file, collegarsi a database, inizializzare variabili e svolgere ogni altra attività necessaria prima che un oggetto possa essere usato.A New constructor can be used to open files, connect to databases, initialize variables, and take care of any other tasks that need to be done before an object can be used.

Quando viene creata un'istanza di una classe derivata, viene eseguito innanzitutto il costruttore Sub New della classe base, seguito dai costruttori delle classi derivate.When an instance of a derived class is created, the Sub New constructor of the base class executes first, followed by constructors in derived classes. Nella prima riga del codice di un costruttore Sub New, infatti, viene usata la sintassi MyBase.New() per chiamare il costruttore della classe immediatamente superiore nella gerarchia delle classi.This happens because the first line of code in a Sub New constructor uses the syntax MyBase.New()to call the constructor of the class immediately above itself in the class hierarchy. Viene quindi eseguita la chiamata al costruttore Sub New di ogni classe della gerarchia fino al raggiungimento del costruttore della classe base.The Sub New constructor is then called for each class in the class hierarchy until the constructor for the base class is reached. A quel punto viene eseguito il codice del costruttore della classe base, seguito dal codice del costruttore di tutte le classi derivate. In ultimo viene eseguito il codice delle classi derivate di livello più basso.At that point, the code in the constructor for the base class executes, followed by the code in each constructor in all derived classes and the code in the most derived classes is executed last.

Screenshot che mostra i costruttori e l'ereditarietà della gerarchia di classi.

Quando un oggetto non è più necessario, prima di liberare la memoria corrispondente viene chiamato il metodo Finalize relativo a quell'oggetto.When an object is no longer needed, the CLR calls the Finalize method for that object before freeing its memory. Il metodo Finalize è denominato destructor, perché consente di eseguire attività di pulizia, quali il salvataggio delle informazioni sullo stato, la chiusura dei file e delle connessioni ai database e altre attività necessarie prima del rilascio dell'oggetto.The Finalize method is called a destructor because it performs cleanup tasks, such as saving state information, closing files and connections to databases, and other tasks that must be done before releasing the object.

Screenshot che illustra il distruttore del metodo Finalize.

Interfaccia IDisposableIDisposable Interface

Le istanze di classe controllano spesso risorse non gestite da CLR, quali gli handle di Windows e le connessioni al database.Class instances often control resources not managed by the CLR, such as Windows handles and database connections. È necessario eliminare definitivamente queste risorse nel metodo Finalize della classe per consentirne il rilascio quando il Garbage Collector elimina definitivamente l'oggetto.These resources must be disposed of in the Finalize method of the class, so that they will be released when the object is destroyed by the garbage collector. Tuttavia, poiché il Garbage Collector elimina definitivamente gli oggetti solo quando CLR richiede la disponibilità di maggiore memoria,However, the garbage collector destroys objects only when the CLR requires more free memory. è possibile che le risorse vengano rilasciate solo molto tempo dopo l'abbandono dell'ambito da parte dell'oggetto.This means that the resources may not be released until long after the object goes out of scope.

A supporto del Garbage Collector, le classi possono implementare l'interfaccia IDisposable per fornire un sistema di gestione attiva delle risorse di sistema.To supplement garbage collection, your classes can provide a mechanism to actively manage system resources if they implement the IDisposable interface. IDisposable dispone di un metodo, Dispose, che i client devono chiamare al termine dell'utilizzo di un oggetto.IDisposable has one method, Dispose, which clients should call when they finish using an object. È possibile usare il metodo Dispose per rilasciare immediatamente risorse ed eseguire attività quali la chiusura di file e le connessioni al database.You can use the Dispose method to immediately release resources and perform tasks such as closing files and database connections. A differenza del distruttore Finalize, il metodo Dispose non viene chiamato automaticamente.Unlike the Finalize destructor, the Dispose method is not called automatically. Quando si vogliono rilasciare immediatamente risorse, è necessario che i client di una classe chiamino in modo esplicito il metodo Dispose.Clients of a class must explicitly call Dispose when you want to immediately release resources.

Implementazione di IDisposableImplementing IDisposable

Una classe che implementa l'interfaccia IDisposable deve includere il codice seguente:A class that implements the IDisposable interface should include these sections of code:

  • Campo che consente di controllare se l'oggetto è stato eliminato in modo permanente:A field for keeping track of whether the object has been disposed:

    Protected disposed As Boolean = False
    
  • Overload del metodo Dispose che consente di liberare le risorse della classe.An overload of the Dispose that frees the class's resources. Questo metodo deve essere chiamato dai metodi Dispose e Finalize della classe base:This method should be called by the Dispose and Finalize methods of the base class:

    Protected Overridable Sub Dispose(ByVal disposing As Boolean)
        If Not Me.disposed Then
            If disposing Then
                ' Insert code to free managed resources.
            End If
            ' Insert code to free unmanaged resources.
        End If
        Me.disposed = True
    End Sub
    
  • Implementazione di Dispose che contiene solo il codice seguente:An implementation of Dispose that contains only the following code:

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
        GC.SuppressFinalize(Me)
    End Sub
    
  • Override del metodo Finalize che contiene solo il codice seguente:An override of the Finalize method that contains only the following code:

    Protected Overrides Sub Finalize()
        Dispose(False)
        MyBase.Finalize()
    End Sub
    

Derivazione da una classe che implementa IDisposableDeriving from a Class that Implements IDisposable

Non è necessario eseguire l'override di tutti i metodi di base in una classe derivata da una classe base che implementa l'interfaccia IDisposable, a meno che tale classe non usi risorse aggiuntive che devono essere eliminate in modo permanente.A class that derives from a base class that implements the IDisposable interface does not need to override any of the base methods unless it uses additional resources that need to be disposed. In questo caso, la classe derivata deve eseguire l'override del metodo Dispose(disposing) della classe base per eliminare in modo permanente le risorse della classe derivata.In that situation, the derived class should override the base class's Dispose(disposing) method to dispose of the derived class's resources. Inoltre, tale override deve chiamare il metodo Dispose(disposing) della classe base.This override must call the base class's Dispose(disposing) method.

Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    If Not Me.disposed Then
        If disposing Then
            ' Insert code to free managed resources.
        End If
        ' Insert code to free unmanaged resources.
    End If
    MyBase.Dispose(disposing)
End Sub

Una classe derivata non deve eseguire l'override del metodi Dispose e Finalize della classe base.A derived class should not override the base class's Dispose and Finalize methods. Infatti, quando questi metodi vengono chiamati da un'istanza della classe derivata, la relativa implementazione della classe base chiama l'override del metodo Dispose(disposing) della classe derivata.When those methods are called from an instance of the derived class, the base class's implementation of those methods call the derived class's override of the Dispose(disposing) method.

Garbage Collection e il distruttore FinalizeGarbage Collection and the Finalize Destructor

Il .NET Framework usa il sistema di Garbage Collection di traccia di riferimento per rilasciare periodicamente le risorse inutilizzate.The .NET Framework uses the reference-tracing garbage collection system to periodically release unused resources. Visual Basic 6,0 e versioni precedenti usavano un sistema diverso denominato conteggio dei riferimenti per gestire le risorse.Visual Basic 6.0 and earlier versions used a different system called reference counting to manage resources. Anche se in entrambi i casi viene eseguita automaticamente la stessa funzione, vi sono alcune importanti differenze.Although both systems perform the same function automatically, there are a few important differences.

Mediante il metodo CLR gli oggetti vengono eliminati definitivamente con cadenza periodica quando il sistema stabilisce che non sono più necessari.The CLR periodically destroys objects when the system determines that such objects are no longer needed. Gli oggetti vengono rilasciati più rapidamente quando le risorse di sistema sono insufficienti e con una frequenza minore in caso contrario.Objects are released more quickly when system resources are in short supply, and less frequently otherwise. Il ritardo tra il momento in cui un oggetto abbandona l'ambito e il relativo rilascio da parte di CLR indica che, a differenza di quanto avveniva in Visual Basic 6.0 e nelle versioni precedenti, non è possibile stabilire esattamente quando l'oggetto verrà eliminato in modo permanente.The delay between when an object loses scope and when the CLR releases it means that, unlike with objects in Visual Basic 6.0 and earlier versions, you cannot determine exactly when the object will be destroyed. In una situazione di questo tipo, si dice che gli oggetti hanno una durata non deterministica.In such a situation, objects are said to have non-deterministic lifetime. Nella maggior parte dei casi la durata non deterministica non influisce sulla modalità di scrittura delle applicazioni, purché si ricordi che è possibile che il distruttore Finalize non venga eseguito immediatamente dopo la perdita di ambito di un oggetto.In most cases, non-deterministic lifetime does not change how you write applications, as long as you remember that the Finalize destructor may not immediately execute when an object loses scope.

Un'altra differenza tra i sistemi di Garbage Collection riguarda l'uso di Nothing.Another difference between the garbage-collection systems involves the use of Nothing. Per poter usare il conteggio dei riferimenti, in Visual Basic 6.0 e nelle versioni precedenti, a volte veniva assegnato Nothing alle variabili oggetto in modo da rilasciare i riferimenti contenuti in tali variabili.To take advantage of reference counting in Visual Basic 6.0 and earlier versions, programmers sometimes assigned Nothing to object variables to release the references those variables held. Se la variabile conteneva l'ultimo riferimento all'oggetto, le risorse dell'oggetto venivano rilasciate immediatamente.If the variable held the last reference to the object, the object's resources were released immediately. Anche se in alcuni casi questa routine può risultare ancora utile, la sua esecuzione nelle versioni successive di Visual Basic non risulta mai nel rilascio immediato delle risorse da parte dell'oggetto a cui si fa riferimento.In later versions of Visual Basic, while there may be cases in which this procedure is still valuable, performing it never causes the referenced object to release its resources immediately. Per rilasciare subito le risorse, usare il metodo Dispose dell'oggetto, se disponibile.To release resources immediately, use the object's Dispose method, if available. Si consiglia di impostare una variabile su Nothing solo nel caso in cui la durata della variabile risulti lunga in relazione al tempo necessario per l'individuazione degli oggetti isolati tramite le operazioni del Garbage Collector.The only time you should set a variable to Nothing is when its lifetime is long relative to the time the garbage collector takes to detect orphaned objects.

Vedere ancheSee also