I.T. Discussion Community!
-Collapse +Expand
Prism
Search Prism Group:

Advanced
-Collapse +Expand Prism To/From
To/FromCODEGuides
-Collapse +Expand Prism Study Test
PRESTWOODCERTIFIED
-Collapse +Expand Prism Store
PRESTWOODSTORE

Prestwood eMagazine

February Edition
Subscribe now! It's Free!
Enter your email:

   ► KBProgrammingDelphi PrismOOP   Print This     
  From the November 2015 Issue of Prestwood eMag
 
Prism OOP:
Delphi Prism Finalizer (finalize())
 
Posted 10 years ago on 1/23/2009 and updated 9/15/2009
Prism Code Snippet:
 A flashcard from our Prism Flashcards Library
 A code snippet from our Prism Code Snippets Page

KB101848



General Info: Class Destructor

A 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 Focus: Destructor

Are object instances freed with a garbage collector? Or, do you have to destroy object instances.

Delphi Prism Finalizer

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
  Cyborg = class(IDisposable)
  private
    disposed: Boolean;
    method Dispose(disposing: Boolean);
  public
    method Dispose;
    finalizer Finalize;
  end;

Important Notes

  • Each class has one and only one finalizer.
  • The name of the finalizer is always Finalize.
  • You cannot call a finalizer, nor can you overload it.
  • You cannot predict with certainty when it will be called.

Working WinForms Example

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.

Implementing IDisposable

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.

Add IDisposable to Your Class

//
//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;

Using IDisposable

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;

Working IDisposable Example

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.

Q. If I implement IDisposable, can I also let the garbage collector free my objects?

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.

Q. If I consume an object that implements IDisposable, should I always call Dispose?

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.

More Info

Definition:  Class Destructor
Code:  Delphi Prism Constructors (constructor + class name)

Comments

0 Comments.
Share a thought or comment...
 
Write a Comment...
...
Sign in...

If you are a member, Sign In. Or, you can Create a Free account now.


Anonymous Post (text-only, no HTML):

Enter your name and security key.

Your Name:
Security key = P1226A1
Enter key:
Code Contributed By Mike Prestwood:

Mike Prestwood is a drummer, an author, and creator of the PrestwoodBoards online community. He is the President & CEO of Prestwood IT Solutions. Prestwood IT provides Coding, Website, and Computer Tech services. Mike has authored 6 computer books and over 1,200 articles. As a drummer, he maintains play-drums.com and has authored 3 drum books. If you have a project you wish to discuss with Mike, you can send him a private message through his PrestwoodBoards home page or call him 9AM to 4PM PST at 916-726-5675 x205.

Visit Profile


Linked Certification Question(s)

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.

Beginner

1 Beginner Level Question

Question #1: True or False?

Each class can have one and only one finalizer.

Answer:
  • True
  • False
  • Intermediate

    1 Intermediate Level Question

    Question #2: True or False?

    The traditional name for a finalizer is Finalize but you can call it anything you want.

    Answer:
  • True
  • False

  •  KB Article #101848 Counter
    19090
    Since 1/23/2009
    -
       Contact Us!
     
    PrestwoodBoards.com was developed and is maintainted by me. Do you have a question or suggestion? Do you see a problem? Contact me now. My goal is to build an ad-free and spam-free source of I.T. information with many contributers (ok to promote your website/company in your bio). Yes, my company Prestwood IT Solutions is mentioned in my bio which shows with every post, but you can contribute and promote your pet project too!

    2,129 People Online Now!!  
    Sign In to see who's online now!  Not a member? Join now. It's free!
    Show more stats...


    ©1995-2019 PrestwoodBoards  [Security & Privacy]
    Professional IT Services: Coding | Websites | Computer Tech