Destructor in C#

原创 2004年06月23日 12:03:00
Author Date Of Submission User Level
Neeraj Saluja 05/12/2004 Beginner

The article introduces destructors and how they are implemented in C#. Let us start by defining destructors in simple terms.

Destructor is method in the class which is aimed to release the resources that the instance of the class has acquired. This method is called by CLR when the instance of the class is getting destructed.

Since this method is executed at the time of destruction of the instance of the class, it is but obvious that it is meant for releasing the resources acquired by the objects as the instance will be no more in existence after executing this method. This does not mean that developer cannot write any other code - he/she can. The complete onus is on developer of whatever is written in that method. It is simply like any other method written with the specific aim. The developer could use it to log some information using this method so it all depends on the developer what to use it for.

How a destructor looks like, here is the sample:
 
public class myclass
{
        public myclass()
        {
                  // This is the constructor method of myclass.
        }

       ~myclass()
        {
                  // This is the destructor method of myclass.
        }
}

Few things to note here, before we get into details:

1. Destructor does not have access modifiers like public, private etc.
2. The destructor is like any other member method. The code could aim to anything, but the basic intention of this method is the release of the memory.
3. Destructors are called automatically by CLR, and to be more specific garbage collector; the developer cannot call them explicitly.
4. Overloaded destructor is not possible. One class can thus have at the most one destructor which is parameter less.
5. Destructors cannot be inherited.

Destructors in Inheritance scenario

Let us now see what happens when the classes with the destructors are involved in inheritance. Let us see this thing by an example. Have a look at the following console application:

// Neeraj Saluja [neeraj_saluja@indiatimes.com]
// Console Application to show behavior of Destructors in Inheritance.
using System;

namespace DestructorsExample
{

      ///
      /// The base class for Class2
      ///
      class Class1
      {
             ~Class1()
             {
                    Console.WriteLine("Destructor of Class1");
             }
      }
      ///
      /// Class2 inherting Class1
      ///
      class Class2 : Class1
      {
             ~Class2()
             {
                    Console.WriteLine("Destructor of Class2");
             }
      }
      ///
      /// MainClass.
      ///
      class MainClass
      {
             ///
             /// The main entry point for the application.
             ///
             [STAThread]
             static void Main(string[] args)
            {
                    Class2 objClass2 = new Class2();
            }
      }
}

What do you think should be the sequence of execution of destructors here ? Here is the output:

      Destructor of Class2
      Destructor of Class1

The thing that should be noted here is, we don抰 know when the destructor will be called but we always know in what sequence these executes when it comes to inheritance.

What抯 happening Internally
Let us now see how .Net is handling destructor. When you write a destructor, the compiler internally calls the Finalize() method of Object class after executing your destructor code. Let us look at the MSIL code of the Finalize method of class2:

.method family hidebysig virtual instance void
Finalize() cil managed
{
 // Code size 20 (0x14)
 .maxstack 1
 .try
 {
  IL_0000: ldstr "Destructor of Class2"
  IL_0005: call void [mscorlib]System.Console::WriteLine(string)
  IL_000a: leave.s IL_0013
 } // end .try
 finally
 {
  IL_000c: ldarg.0
  IL_000d: call instance void DestructorsExample.Class1::Finalize()
  IL_0012: endfinally
 } // end handler
 IL_0013: ret
} // end of method Class2::Finalize

You can get the above look by using the tool ildasm.exe.

Note that it first executes the destructor of the current class in the try block followed by the destructor of base class in the finally block.

If the class does not posses any destructor, the complete memory management is done by garbage collector. The garbage collector is designed to take care of release of memory of objects of each class. If you provide the destructor to the class, the destructor gets executed when the object destructs plus when the garbage collector takes it for cleaning. So it means by default your object of the class will undergo cleaning of resources twice. Well, you can tell the garbage collector to ignore the object of your class for clean up process. To do so, write the statement,  System.GC.SuppressFinalize in your destructor code. For further reference on methods of GC you can refer to MSDN.

Destructors FAQs

1. When should one write the destructor and when not?
 
The basic aim of destructor is to release the resources and memory held by the object. In    general you should not be worried about memory management as garbage collector takes cares of it in a beautiful way.

    However, when your class holds some unmanaged resources like files, network connection etc then you should use destructor. Also, when expensive external resources (though managed) are involved then also it is recommended to have destructor rather than waiting for garbage collector to do it.

2. Classes and Structs both have methods, can we have destructor for the Structs too?
No. Structs can not have destructor. Destructor is specifically meant for classes.

3. Can I force the garbage collector to release memory?
Yes, you can, using the syntax System.GC.Collect method. It is the overloaded method. But be sure of its implications before using this syntax ?it can lead to a performance issue. It is because when you are asking garbage collector to release the memory, it will try to release the memory in its own mechanism taking the entire memory into consideration, which could be resource consuming at that moment of time.

4. Can I have both the destructor and overloaded Finalize method in my class?
    
Logically speaking it is not required. Anyway, if somebody tries to write both then one will get the compile time error similar to this : 揅lass 'DestructorsExample.Class2' already defines a member called 'Finalize' with the same parameter types? This is because destructors are ultimately converted into Finalize method.

5. Where is this Finalize method came from ?I haven抰 inherited System.Object class?
The master base of all the classes is the System.Object class. And if you do not provide any class for inheritance the compiler automatically inherits the System.Object class for your class. So each class knowingly or unknowingly inherits this class.

6. What happens if the code inside the destructor raises an exception?
The CLR runtime ignores that exception and moves further. Say for example if your Class2   destructor looks something like this :

~Class2()
{
Console.WriteLine("Destructor of Class2");
System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection("some wrong
connection string here");
}

Then the output of the above program would something like this:

Destructor of Class2

Unhandled Exception: System.ArgumentException: Expected '=' delimiter while pars
ing connection value pair.
  at System.Data.SqlClient.ConStringUtil.ParseStringIntoHashtable(String conStr
 ing, Hashtable values)
  at System.Data.SqlClient.ConStringUtil.ParseConnectionString(String connectio
 nString)
  at System.Data.SqlClient.SqlConnection.set_ConnectionString(String value)
  at System.Data.SqlClient.SqlConnection..ctor(String connectionString)
  at DestructorsExample.Class2.Finalize()
Destructor of Class1


 

C++对象模型——临时性对象 (第六章)

6.3    临时性对象 (Temporary Objects)     如果有一个函数,形式如下: T operator+(const T &, const T &);    以及两个T obje...
  • yiranant
  • yiranant
  • 2015年08月17日 22:40
  • 467

c++:构造函数(constructor)和析构函数(destructor)中编译器的隐式行为(implicit behavior)

【注:心急的可以通过目录直接看每段的结论;更心急的可以直接跳到最后看总结。但是这样的看法估计和教材里学到的差不多】 上篇文章提到,c++为了保证向前的兼容性和新加入的各种花哨功能,引入了很多隐式行为...
  • madongchunqiu
  • madongchunqiu
  • 2014年03月28日 22:37
  • 4721

C++析构函数(Destructor)

创建对象时系统会自动调用构造函数进行初始化工作,同样,销毁对象时系统也会自动调用一个函数来进行清理工作,例如释放分配的内存、关闭打开的文件等,这个函数就是析构函数。 析构函数(Destructo...
  • xiaopang1122
  • xiaopang1122
  • 2017年04月13日 17:30
  • 103

Delphi构造函数和析构函数

 Delphi构造函数和析构函数 2013-08-20 16:31 287人阅读 评论(0) 收藏 举报 本文章已收录于: 分类: ...
  • hewusheng10
  • hewusheng10
  • 2016年09月01日 12:57
  • 2115

CEF3:与 JavaScript 整合(三)—— IPC 通信

本篇介绍如何通过发送 IPC 消息实现 JS 回调函数的异步调用。实现方法渲染进程端: 1、实现 CefV8Handler 以注册 JS 回调函数 2、在 CefRenderProcessHand...
  • u011304970
  • u011304970
  • 2017年09月14日 14:56
  • 398

GCC——选项说明

http://blog.chinaunix.net/uid-553033-id-119977.html GCC Section: GNU Tools (1) Updated: 2003/...
  • ztguang
  • ztguang
  • 2016年02月01日 00:00
  • 1753

嵌入指南|Chrome V8

Embedder's Guide If you've read the Getting Started guide you will already be familiar wi...
  • x_studying
  • x_studying
  • 2015年08月21日 19:20
  • 902

C++ 过滤警告的方法

在iOS开发过程中, 我们可能会碰到一些系统方法弃用, weak、循环引用、不能执行之类的警告。 有代码洁癖的孩子们很想消除他们, 今天就让我们来一次Fuck 警告!! 首先学会基本的语句 #prag...
  • or7rccl
  • or7rccl
  • 2017年11月19日 18:09
  • 240

g++版本太低了,连iostream都不支持

testbigsmall.cpp #include using namespace std; bool bigCheck() {     union Check     {  ...
  • michaelysj
  • michaelysj
  • 2017年03月19日 15:37
  • 360

Linux内核中网络数据包的接收-第一部分 概念和框架

与网络数据包的发送不同,网络收包是异步的的,因为你不确定谁会在什么时候突然发一个网络包给你,因此这个网络收包逻辑其实包含两件事:1.数据包到来后的通知2.收到通知并从数据包中获取数据这两件事发生在协议...
  • dog250
  • dog250
  • 2016年01月16日 15:26
  • 6295
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Destructor in C#
举报原因:
原因补充:

(最多只允许输入30个字)