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

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

Prestwood eMagazine

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

   ► KBProgrammingC#OOP   Print This     
  From the January 2016 Issue of Prestwood eMag
 
C# OOP:
C# Finalizer (~ClassName)
 
Posted 10 years ago on 1/18/2009
C# Code Snippet:
 A flashcard from our C# Flashcards Library
 A code snippet from our C# Code Snippets Page

KB101834



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.

C# Finalizer

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 {
public:
//Destructor for class Cyborg.
~Cyborg();
  {
  //Free non-managed resources here.
  }
};

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:

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.");
}

}

}

 

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

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);
}
}

Using IDisposable

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(); 

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. 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:

Picture for KB article.

After you implement the code below, perform the following use cases:

  • Click the Instantiate Object Only button and close the form. The GC cleans up upon close of the form.
  • Click the Instantiate Objects Only button then click the GC.Collect button. The GC cleans up at that time.
  • Click the Instantiate and Dispose button. Notice the objects are disposed of in the click event. Then close the form and notice your finalizer code is never executed.

Complete Code:

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);
    }
  }
}

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

Code:  C# Constructors (Use class name)
Definition:  Class Destructor

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 = P1222A1
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.

Advanced

1 Advanced Level Question

Question #1: Multiple Choice

Given the following code snippet:

public class Cyborg
{
}
Answer:
1. 

The finalizer method name must be Finalize.

2. 

The finalizer method name must be ~Cyborg.

3. 

The finalizer method name must be Destroy.

4. 

The finalizer method name must be Dispose.

5. 

The finalizer method name can be any method name of your choosing so long as you use the finalizer keyword to indicate this is the finalizer method.


 KB Article #101834 Counter
15118
Since 1/18/2009
Follow PrestwoodBoards on: 


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