|
IT SOLUTIONS
Your full service technology partner!
|
|
![]() ![]() |
|
General Info: Class DestructorA special class method called when an object instance of a class is destroyed. With some languages they are called when the object instance goes out of scope, with some languages you specifically have to call the destructor in code to destroy the object, and others use a garbage collector to dispose of object instances at specific times. Desctructors are commonly used to free the object instance but with languages that have a garbage collector object instances are disposed of when appropriate. Either way, destructors or their equivalent are commonly used to free up resources allocated in the class constructor. Languages FocusAre object instances freed with a garbage collector? Or, do you have to destroy object instances.
More Info![]()
![]()
|
ASP Classic: Class_TerminateWhen an object instance is destroyed, ASP calls a special parameter-less sub named Class_Terminate. For example, when the variable falls out of scope. Since you cannot specify parameters for this sub, you also cannot overload it. To explicitly destroy an object, use Set YourClass = nothing. If the Class object is explicitly destroyed, the client returns with the script engine error details. When an object instance is created from a class, ASP calls a special sub called Class_Initialize.
Working ExampleThe following working example contains both a constructor and destructor, ASP's Class_Initialize and Class_Terminate subs. In this example, we are explicitly destroying the object by using Set MyRobot = Nothing. In ASP Classic, it is recommended that you explicitly destroy all objects. <%@LANGUAGE=VBScript%> <% Set MyRobot = new Cyborg //Explicitly destroy object. Set MyRobot = Nothing </body> <% Public Sub Class_Terminate
|
![]() |
ASP Classic Destructor (Class_Terminate) |
![]() |
Class Destructor |
In C# you cannot explicitly destroy a managed object. Instead, the .Net Framework's garbage collector (GC) takes care of destroying all objects. The GC destroys the objects only when necessary. Some situations of necessity are when memory is exhausted or you explicitly call the System.GC.Collect() method. In general, you never need to call System.GC.Collect().
In .Net, a finalizer is used to free non-managed objects such as a file or network resource. In C#, a finalizer is a method with the same name as the class but preceded with a tilde (as in ~ClassName). The finalizer method implicity creates an Object.Finalize method (you cannot directly call nor override the Object.Finalize method). Because you don't know when the garbage collector will call your finalizer, Microsoft recommends you implement the IDisposable interface for non-managed resources and call it's Dispose() method at the appropriate time.
Syntax Example:class Cyborg { { //Free non-managed resources here. } |
The following demonstrates using a finalizer and System.GC.Collect(). I placed a MessageBox.Show() in the finalizer so you can see when it is called. The finalizer gets called when the compiler needs to free resources or you call System.GC.Collect(). You'll notice that although the local variable in the button click event falls out of scope, your finalizer is not called until either you close the form or click the button that calls System.GC.Collect().
Create a form with two buttons and add code as follows:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace CR_Constructor
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//Create and use object instance.
Cyborg MyRobot = new Cyborg("Cameron");
MessageBox.Show("My robot's name is " + MyRobot.CyborgName);
}
private void button2_Click(object sender, EventArgs e)
{
//Explicitly call garbage collector (never required for managed code).
System.GC.Collect();
}
}
public class Cyborg: Object
{
public string CyborgName;
//Constructor.
public Cyborg(string pName)
{
CyborgName = pName;
}
//Finalizer.
~Cyborg()
{
MessageBox.Show("Free non-managed resources here.");
}
}
}
If you wish to have control over freeing the objects you create (either managed or unmanaged object instances), use the IDisposable interface and add it to your class and implement according to the standard IDisposable pattern.
public class Cyborg: Object, IDisposable
{
private bool disposed = false;
// Do not make this method virtual.
// Don't let a descendant class override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Call GC.SupressFinalize to remove from GC queue.
GC.SuppressFinalize(this);
}
// Dispose of managed and/or unmanaged resources.
private void Dispose(bool disposing)
{
if(!this.disposed)
{
if(disposing)
{
//Free managed resources here.
}
// Free unmanaged resources here.
//Indicated disposing completed.
disposed = true;
}
}
//Finalizer.
~Cyborg()
{
Dispose(false);
}
}
Once implemented you can free object instances by calling Dispose.
Cyborg MyRobot1 = new Cyborg();
MyRobot1.CyborgName = "John";
MessageBox.Show("My robot's name is " + MyRobot1.CyborgName);
MyRobot1.Dispose();
In the following example, we implement the IDisposable interface in our Cyborg class from above and call Dispose in the button's click event. You'll notice that whether you click our second button that calls System.GC.Collect or exit the form, the dialog in our finalizer is never displayed because the managed object instances that were used are already disposed of properly. In this implementation, if you forget to call Dispose, the GC will clean up the object at an appropriate time and call your finalizer.
Setup form:
After you implement the code below, perform the following use cases:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace CR_Constructor
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Cyborg MyRobot1 = new Cyborg();
MyRobot1.CyborgName = "John";
MessageBox.Show("My robot's name is " + MyRobot1.CyborgName);
Cyborg MyRobot2 = new Cyborg("Cameron");
MessageBox.Show("My robot's name is " + MyRobot2.CyborgName);
}
private void button2_Click(object sender, EventArgs e)
{
System.GC.Collect();
}
private void button3_Click(object sender, EventArgs e)
{
Cyborg MyRobot1 = new Cyborg();
MyRobot1.CyborgName = "John";
MessageBox.Show("My robot's name is " + MyRobot1.CyborgName);
Cyborg MyRobot2 = new Cyborg("Cameron");
MessageBox.Show("My robot's name is " + MyRobot2.CyborgName);
MyRobot1.Dispose();
MyRobot2.Dispose();
}
}
public class Cyborg: Object, IDisposable
{
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
MessageBox.Show("Dispose executed.");
}
private void Dispose(bool disposing)
{
if(!this.disposed)
{
if(disposing)
{
//Free managed resources here.
}
// Free unmanaged resources here.
disposed = true;
}
}
public string CyborgName;
public Cyborg() { }
public Cyborg(string pName)
{
CyborgName = pName;
}
~Cyborg()
{
MessageBox.Show("If we call Dispose, does this execute? No.");
Dispose(false);
}
}
}
A. It depends on how you implemented IDisposable and how you are using resources. In general, if you implement IDisposable you should take ownership of calling Dispose for each object instance you create. However, in the simple Working IDisposable Example in this article, you can either call Dispose to free the objects or let the garbage collector free them as demonstrated by the button click events.
A. In general, yes if it's a shared resource. However, again it depends on why IDisposable was implemented. If Dispose is freeing a resource that may be needed, like a file handle, then yes. There may be exceptions to this rule, but if an object implements IDisposable and the resource is a shared resource, then yes when you create an object instance, you should take ownership and also call Dispose at the appropriate time.
The following are practice certification questions with answers highlighted. These questions were prepared by Mike Prestwood and are intended to stress an important aspect of this KB post. All our practice questions are intended to prepare you generally for passing any certification test as well as prepare you for professional work.
1 Advanced Level Question
![]() |
C# Constructors (Use class name) |
![]() |
C# Finalizer (~ClassName) |
![]() |
Class Destructor |
A member function with the same name as the class prefixed with a ~ (tilde). C++ destructors are automatically called when an object goes out of scope, or when you delete a dynamically allocated object. Every class can have only one destructor.
Syntax Example:
class Cyborg {
More Info![]()
|
Unlike standard C++, C++/CLI uses the .Net garbage collector to free managed object instances. Prism does not have nor need a true destructor.
In .Net, a finalizer is used to free non-managed objects such as a file or network resource. Because you don't know when the garbage collector will call your finalizer, Microsoft recommends you implement the IDisposable interface for non-managed resources and call it's Dispose() method at the appropriate time.
More Info / Comment![]() |
Class Destructor |
Object Pascal uses a standard virtual destructor named Destroy which is called by the standard Free method. All objects are dynamic, so you need to call MyObject.Free method or the FreeAndNil(MyObject) routine for each object you create.
Syntax Example:
var //Use it... MyObject.Free //Or use...FreeAndNil(MyObject);
|
![]() |
Class Destructor |
Unlike Delphi, Delphi Prism uses the .Net garbage collector to free managed object instances. Prism does not have nor need a true destructor.
In .Net, a finalizer is used to free non-managed objects such as a file or network resource. In Prism, you use the keyword finalizer to indicate the method is a finalizer. Each class can implement one and only one finalizer with a method name of finalize(), which is the method name used in Java and VB.Net.
Because you don't know when the garbage collector will call your finalizer, For non-managed resources, Microsoft recommends you implement the IDisposable interface and call it's Dispose() method at the appropriate time.
Syntax Example:type |
The following demonstrates using a finalizer and System.GC.Collect(). I placed a MessageBox.Show() in the finalizer so you can see when it is called. The finalizer gets called when the compiler needs to free resources or you call System.GC.Collect(). You'll notice that although the local variable in the button click event falls out of scope, your finalizer is not called until either you close the form or click the button that calls System.GC.Collect().
Create a form with two buttons and add code as follows:
namespace CR_Constructor;
interface
uses
System.Drawing,
System.Collections,
System.Collections.Generic,
System.Linq,
System.Windows.Forms,
System.ComponentModel;
type
/// <summary>
/// Summary description for MainForm.
/// </summary>
MainForm = partial class(System.Windows.Forms.Form)
private
method button1_Click(sender: System.Object; e: System.EventArgs);
method button2_Click(sender: System.Object; e: System.EventArgs);
protected
method Dispose(disposing: Boolean); override;
public
constructor;
end;
Cyborg = class(System.Object)
private
public
property CyborgName: String; //Property using implicit syntax.
constructor();
constructor(pName: String);
//This is the full version of a finalizer.
finalizer Finalize;
//As with constructors, you could have just used the keyword.
//finalizer;
end;
implementation
{$REGION Construction and Disposition}
constructor MainForm;
begin
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
end;
method MainForm.Dispose(disposing: Boolean);
begin
if disposing then begin
if assigned(components) then
components.Dispose();
//
// TODO: Add custom disposition code here
//
end;
inherited Dispose(disposing);
end;
{$ENDREGION}
method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
var
MyRobot1: Cyborg;
MyRobot2: Cyborg;
begin
MyRobot1 := New Cyborg;
MyRobot1.CyborgName := "John";
MessageBox.Show("My robot's name is " + MyRobot1.CyborgName + ".");
MyRobot2 := New Cyborg("Cameron");
MessageBox.Show("My robot's name is " + MyRobot2.CyborgName + ".");
end;
method MainForm.button2_Click(sender: System.Object; e: System.EventArgs);
begin
System.GC.Collect;
end;
constructor Cyborg();
begin
end;
constructor Cyborg(pName: String);
begin
CyborgName := pName;
end;
finalizer Cyborg.Finalize;
begin
MessageBox.Show("In finalizer.");
end;
end.
If you wish to have control over freeing the objects you create (either managed or unmanaged object instances), use the IDisposable interface and add it to your class and implement according to the standard IDisposable pattern.
//
//Interface
//
//1. Add IDisposable interface to inheritance syntax
// and add two Dispose methods and a member field boolean.
Cyborg = class(System.Object, IDisposable)
private
disposed: Boolean;
method Dispose(disposing: Boolean);
public
finalizer Finalize;
method Dispose;
end;
//
//Implementation
//
//2. Implement the two dispose methods.
method Cyborg.Dispose;
begin
Dispose(true);
GC.SuppressFinalize(self);
end;
method Cyborg.Dispose(disposing: Boolean);
begin
if not disposed then
begin
if disposing then
begin
// Dispose of managed resources.
end;
// Dispose of unmanaged resources
disposed := true;
end
end;
//3. Set your boolean to false in finalizer
// using your Dispose() method.
finalizer Cyborg.Finalize;
begin
Dispose(false);
end;
Once implemented you can free object instances by calling Dispose.
var MyRobot1: Cyborg;
MyRobot1 := New Cyborg;
MyRobot1.CyborgName := "John";
MessageBox.Show("My robot's name is " + MyRobot1.CyborgName + ".");
MyRobot1.Dispose;
In the following example, we implement the IDisposable interface in our Cyborg class from above and call Dispose in the button's click event. You'll notice that whether you click our second button that calls System.GC.Collect or exit the form, the dialog in our finalizer is never displayed because the managed object instances that were used are already disposed of properly.
namespace CR_Constructor;
interface
uses
System.Drawing,
System.Collections,
System.Collections.Generic,
System.Linq,
System.Windows.Forms,
System.ComponentModel;
type
/// <summary>
/// Summary description for MainForm.
/// </summary>
MainForm = partial class(System.Windows.Forms.Form)
private
method button1_Click(sender: System.Object; e: System.EventArgs);
method button2_Click(sender: System.Object; e: System.EventArgs);
protected
method Dispose(disposing: Boolean); override;
public
constructor;
end;
Cyborg = class(System.Object, IDisposable)
private
disposed: Boolean;
method Dispose(disposing: Boolean);
public
property CyborgName: String;
constructor;
constructor(pName: String);
finalizer Finalize;
method Dispose;
end;
implementation
{$REGION Construction and Disposition}
constructor MainForm;
begin
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
end;
method MainForm.Dispose(disposing: Boolean);
begin
if disposing then begin
if assigned(components) then
components.Dispose();
//
// TODO: Add custom disposition code here
//
end;
inherited Dispose(disposing);
end;
{$ENDREGION}
method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
begin
var MyRobot1: Cyborg;
var MyRobot2: Cyborg;
MyRobot1 := New Cyborg;
MyRobot1.CyborgName := "John";
MessageBox.Show("My robot's name is " + MyRobot1.CyborgName + ".");
MyRobot2 := New Cyborg("Cameron");
MessageBox.Show("My robot's name is " + MyRobot2.CyborgName + ".");
MyRobot1.Dispose;
MyRobot2.Dispose;
end;
method MainForm.button2_Click(sender: System.Object; e: System.EventArgs);
begin
System.GC.Collect;
end;
constructor Cyborg();
begin
end;
constructor Cyborg(pName: String);
begin
CyborgName := pName;
end;
finalizer Cyborg.Finalize;
begin
Dispose(false);
//This dialog never shows demonstrating the
//finalizer is not called by the garbage collector.
MessageBox.Show("In finalizer");
end;
method Cyborg.Dispose;
begin
Dispose(true);
GC.SuppressFinalize(self);
MessageBox.Show("In Dispose");
end;
method Cyborg.Dispose(disposing: Boolean);
begin
if not disposed then
begin
if disposing then
begin
// Dispose of managed resources.
end;
// Dispose of unmanaged resources
disposed := true;
end
end;
end.
A. It depends on how you implemented IDisposable and how you are using resources. In general, if you implement IDisposable you should take ownership of calling Dispose for each object instance you create. However, in the simple Working IDisposable Example in this article, you can either call Dispose to free the objects or let the garbage collector free them as demonstrated by the button click events.
A. In general, yes if it's a shared resource. However, again it depends on why IDisposable was implemented. If Dispose is freeing a resource that may be needed, like a file handle, then yes. There may be exceptions to this rule, but if an object implements IDisposable and the resource is a shared resource, then yes when you create an object instance, you should take ownership and also call Dispose at the appropriate time.
The following are practice certification questions with answers highlighted. These questions were prepared by Mike Prestwood and are intended to stress an important aspect of this KB post. All our practice questions are intended to prepare you generally for passing any certification test as well as prepare you for professional work.
1 Beginner Level Question
1 Intermediate Level Question
![]() |
Class Destructor |
![]() |
Delphi Prism Constructors (constructor + class name) |
![]() |
Delphi Prism Finalizer (finalize()) |
Java has a garbage collection algorythm that runs as a background task so it has no destructors. You can use the finalize() method to close additonal resources such as file handles.
Syntax Example:
protected void finalize() throws Throwable { More Info![]()
|
When an object instance is destroyed, VB6 calls a special parameter-less sub named Class_Terminate. For example, when the variable falls out of scope. Since you cannot specify parameters for this sub, you also cannot overload it.
To explicitly destroy an object, use Set YourClass = nothing.
When an object instance is created from a class, VB6 calls a special sub called Class_Initialize.
More Info / CommentThe following are practice certification questions with answers highlighted. These questions were prepared by Mike Prestwood and are intended to stress an important aspect of this KB post. All our practice questions are intended to prepare you generally for passing any certification test as well as prepare you for professional work.
1 Advanced Level Question
![]() |
Class Destructor |
In VB.Net you cannot explicitly destroy a managed�object. Instead, the .Net Framework's garbage collector (GC) takes care of destroying all objects. The GC destroys the objects only when necessary. Some situations of necessity are when memory is exhausted or you explicitly call the System.GC.Collect() method. In general, you never need to call System.GC.Collect().
In .Net, a finalizer is used to free non-managed objects such as a file or network resource. In VB.Net, a finalizer is an overridden sub called Finalize. Because you don't know when the garbage collector will call your finalizer, Microsoft recommends you implement the IDisposable interface for non-managed resources and call it's Dispose() method at the appropriate time.
Syntax Example:Class Cyborg |
The following demonstrates using a finalizer and System.GC.Collect(). I placed a MessageBox.Show() in the finalizer so you can see when it is called. The finalizer gets called when the compiler needs to free resources. You'll notice that although the local variable in the button click event falls out of scope, your finalizer is not called until either you close the form or click the button that calls System.GC.Collect().
Create a form with two buttons and add code as follows:
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Create and use object instance.
Dim MyRobot2 As New Cyborg("Cameron")
MessageBox.Show("My robot's name is " & MyRobot2.CyborgName & ".")
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'Explicitly call garbage collector (never required for managed code).
System.GC.Collect()
End Sub
End Class
Public Class Cyborg
Public CyborgName As String
'Constructor.
Public Sub New(ByVal pName As String)
CyborgName = pName
End Sub
'Destructor/finalizer.
Protected Overrides Sub Finalize()
MessageBox.Show("Free non-managed resources here.")
MyBase.Finalize()
End Sub
End Class
Although an Object.Finalize() method is implicitly created even when you do not create a finalizer, you still cannot call it directly. In button1_click, if you try to call MyRobot2.Finalize(), it fails the following error.
Error 1 Overload resolution failed because no 'Finalize' is accessible.
A. It depends on how you implemented IDisposable and how you are using resources. In general, if you implement IDisposable you should take ownership of calling Dispose for each object instance you create. However, in the simple Working IDisposable Example in this article, you can either call Dispose to free the objects or let the garbage collector free them as demonstrated by the button click events.
A. In general, yes if it's a shared resource. However, again it depends on why IDisposable was implemented. If Dispose is freeing a resource that may be needed, like a file handle, then yes. There may be exceptions to this rule, but if an object implements IDisposable and the resource is a shared resource, then yes when you create an object instance, you should take ownership and also call Dispose at the appropriate time.
The following are practice certification questions with answers highlighted. These questions were prepared by Mike Prestwood and are intended to stress an important aspect of this KB post. All our practice questions are intended to prepare you generally for passing any certification test as well as prepare you for professional work.
1 Advanced Level Question
![]() |
Class Destructor |
![]() |
VB.Net Finalizer (Finalize()) |
Go ahead! Use Us! | Call: 916-726-5675 | Or visit our new sales site: www.prestwood.com |
ACCOUNT OVERVIEW:
|
CONTACT US:
Office Hours: 8am-5pm | Mon thru Fri
916-726-5675 (office)
916-726-5676 (fax)
916-595-5675 (text msg)
8421 Auburn Blvd, STE 256
Citrus Heights, CA 95610
|
|
©1995-2023 Prestwood IT Solutions.
[Security & Privacy]
|