上一篇:三层结构 >>
Destructors in C#
By Ansil
Introduction
In the enterprise application development world, the buzzwords arePerformance, Scalability, and Security. I started my career as a VC++programmer, and one fine morning, I was transferred to Web developmentdepartment. Like every C++ programmer, I also was frustrated. I thoughtevery Tom, Dick, and our very own Harry can program in HTML. But, soonI found that the real challenge is to produce high performance,scalable, and reliable applications. And above all that the looselycoupled, stateless nature of web environment is always going to hauntyou.
In order to produce high performance scalable applications, it isimportant to use your resources in an optimized manner. One tip is thatuse your resource as late as you can and free it at the earliest afteryour use. My intention here is to describe the object cleaning upmechanism used in C#.
Destructors
As we all know, ‘Destructors’ are used to destruct instances ofclasses. When we are using destructors in C#, we have to keep in mindthe following things:
A class can only have one destructor. Destructors cannot be inherited or overloaded. Destructors cannot be called. They are invoked automatically. A destructor does not take modifiers or have parameters.
The following is a declaration of a destructor for the class MyClass:
~ MyClass()
{
// Cleaning up code goes here
}
The programmer has no control on when the destructor is going to beexecuted because this is determined by the Garbage Collector. Thegarbage collector checks for objects that are no longer being used bythe application. It considers these objects eligible for destructionand reclaims their memory. Destructors are also called when the programexits. When a destructor executes what is happening behind the scenesis that the destructor implicitly calls the Object.Finalize method on the object@#s base class. Therefore, the preceding destructor code is implicitly translated to:
protected override void Finalize()
{
try
{
// Cleaning up .
}
finally
{
base.Finalize();
}
}
Now, let us look at an example of how destructors are called. We have three classes A, B and C. B is derived from A, and C is derived from B. Each class has their own constructors and destructors. In the main of the class App, we create an object of C.
using System;
class A
{
public A()
{
Console.WriteLine("Creating A");
}
~A()
{
Console.WriteLine("Destroying A");
}
}
class B:A
{
public B()
{
Console.WriteLine("Creating B");
}
~B()
{
Console.WriteLine("Destroying B");
}
}
class C:B
{
public C()
{
Console.WriteLine("Creating C");
}
~C()
{
Console.WriteLine("Destroying C");
}
}
class App
{
public static void Main()
{
C c=new C();
Console.WriteLine("Object Created ");
Console.WriteLine("Press enter to Destroy it");
Console.ReadLine();
c=null;
//GC.Collect();
Console.Read();
}
}
As we expect, the constructors of base classes will be executed andprogram will wait for the user to press @#enter@#. When this occurs, weset the object of class C to null.But the destructors are not executing ..!!?? As we already said, theprogrammer has no control on when the destructor is going to beexecuted because the Garbage Collector determines this. But thedestructors are called when the program exits. You can check this byredirecting the o/p of the program to a text file. I have the outputhere. Notice that the destructors of the base classes are calledbecause behind the scenes base.Finalize() is called.
Creating A
Creating B
Creating C
Object Created
Press enter to Destroy it
Destroying C
Destroying B
Destroying A
So, what do you do if you want to call the destructors once you are finished using the object? There are two ways:
Call the Garbage collector to clean up. Implement Dispose method of IDisposable interface. Calling the garbage collector
You can force the garbage collector to do clean up by calling the GC.Collectmethod, but in most cases, this should be avoided because it may resultin performance issues. In the above program, remove the comment on GC.Collect(). Compile and run it. Now, you can see the destructors being executed in the console itself.
Implement IDisposable interface.
The IDisposable interface contains only one public method with signature void Dispose().We can implement this method to close or release unmanaged resourcessuch as files, streams, and handles held by an instance of the classthat implements this interface. This method is used for all tasksassociated with freeing resources held by an object. When implementingthis method, objects must seek to ensure that all held resources arefreed by propagating the call through the containment hierarchy.
class MyClass:IDisposable
{
public void Dispose()
{
//implementation
}
}
When we implement IDisposable interface, we require discipline to ensure that Dispose is called properly.
Using the Destructor and IDisposable interface together
Public class MyClass:IDisposable
{
private bool IsDisposed=false;
public void Dispose()
{
Dispose(true);
GC.SupressFinalize(this);
}
protected void Dispose(bool Diposing)
{
if(!IsDisposed)
{
if(Disposing)
{
//Clean Up managed resources
}
//Clean up unmanaged resources
}
IsDisposed=true;
}
~MyClass()
{
Dispose(false);
}
}
Here the overload of Dispose(bool)does the cleaning up, and all the cleaning up code is written only inthis method. This method is called by both the destructor and the IDisposable.Dispose(). We should take care that the Dispose(bool) is not called from any where else except from the IDisposable.Dispose() and the destructor.
When a client calls IDisposable.Dispose(), then theclient deliberately wants to clean up the managed and unmanagedresource, and so the cleaning up is done. One thing you must havenoticed is that we called GC.SupressFinalize(this)immediately after we cleaned up the resource. This method tells theGarbage Collector that there is no need to call its destructor becausewe have already done the clean up.
Notice that in the above example, the destructor calls the Dispose with parameter as false.Here, we are ensuring that the Garbage collector collects the managedresources. We only do the cleaning up of unmanaged resource.
Conclusion
Even though we have spent some time implementing the IDisposable interface, what if the client doesn’t call them properly? C# has a cool solution for this. The ‘using’ block. It looks like this:
using (MyClass objCls =new MyClass())
{
}
When the control exits from the using block either by running successfully and reaching the closing braces or by throwing an exception, the IDispose.Dispose() of MyClass will be executed. Remember the object you instantiate must implement the System.IDisposable interface. The using statement defines a scope at the end of which an object will be disposed.
About Ansil
Ansilis an MCAD in .NET and he hails from Trivandrum .He is an independentconsultant and has got software development experiences in ASP.NET ,MFC,Visual C# ,ASP , Sql Server2000 ,C# WebServices , COM+ and XML .Hespends his time reading technical articles ,searching the net forlatest news about various technologies,and he plays cricket and has apassion of watching horror movies .
"First they ignore you;then they laugh at you ;then they fight you ;then you win "
Click here to view Ansil@#s online profile.
下一篇:链表类具有哈希表的功能 >>
相关文章:
- · C#编写的生成缩略图程序
- · 用一个留言簿说明C#操作XML的完全过程
- · 递归枚举排列、组合的C#源码
- · C#反编译微软MSDN2003的帮助文档,并将反编译结果保存到一个SQLSERVER数据库中
- · 用C#轻松在DOTNET中实现缩略图
- · c#中结构与类的区别
- · DES加密算法在C#下的实现
- · C#对XML操作:建立XML(3)
- · 上传图片画带阴影的水印.(C#)
- · Destructors in C#
- · 特洛伊木马服务器源代码(C#)
- · [C#]I/O完成端口的类定义和测试实例
- · 选择文件夹的对话框控件c#
- · C#实现Web文件的上传
- · 用C#实现生成PDF文档
- · 用C#实现生成PDF文档
- · 一个FTP客户端的C#代码
- · C# struct & class Differences
- · C++编程人员容易犯的10个C#错
- · C#冒泡算法!
- · 如何在C#的WinForm中制作饼状图和柱状图
- · 使用响应文件编译C#源文件
- · 用C#写vs插件中的一些Tip
- · 用C#生成中文汉字验证码的基本原理
- · 用托盘控制windows服务的c#实现
- · ASP.NET的实时天气及24小时天气预报(C#)
- · 使用C#代码实现增加用户帐号
- · 用c#写的smtp邮件发送类
- · C# Builder 实现POP3信箱的监视
- · 一个有KeepConnection开关的C#的Database类
- · 一个用C#写的词法分析程序
- · 利用自定义事件实现不同窗体间的通讯 -- C#篇
- · 用C#开发.NET CF 蓝牙通信模块
- · 关于C#下写的Web Service 服务在Delphi下调用时的问题
- · 用C#写的一个简单屏幕保护程序
- · .Net/C#: 利用反射编写通用的 rss 2.0 的 reader
- · C# Programming guidlines
- · QQ验证码识别源代码(C#/NET1.1)
