在.Net Delphi里你调用了Free吗? | |
![]() | |
垃圾回收这个,垃圾回收那个。Delphi开发人员习惯了释放对象 ... 现在.Net垃圾回收机取代了释放对象,问题是:你何时需要或必须释放对象?你应不应该“释放”对象呢?这篇文章提供了解答! |
这是系列文章第三篇,本盗形恼碌奈ㄒ荒康模禾峁┛焖佟⒓虮愕腄elphi for .Net编程入门。
AnObject.Free
我假设你已经写过大量的基于Win32开发解决方案的代码。运行时创建和释放对象是一件很平常的事 ... 在Win32领域,任何对象实例在运行时,如果不再被使用就应被调用Free来销毁,这样它才能被完全销毁并释放占用的内存。换句话说,我们经常用到像下面一样的代码片断:
AnObject := TAnObject.Create(nil); try //......与对象相关的代码 finally AnObject.Free; end; |
当你用完AnObject时,调用“Free”方式确保AnObject占用的内存被释放
“现在”(在.Net领域)他们告诉你:“你不再需要释放你的对象了!”,所有人都正在谈论垃圾回收(GC)。
我困惑了(我相信你也一样)!我应不应该调用Free呢?在.Net里垃圾回收器是什么?一个文件或数据库用完之后我应该关闭它们吗?GDI资源呢(也要不要释放)?
让我们来研究!
垃圾回收器
在.Net框架里,一个新的功能就是垃圾自动回收。垃圾回收这个术语可以定义为:管理在应用程序中分配和释放内存。换句话说,.Net垃圾回收器(GC)完全将你从跟踪内存使用和发觉何时释放内存的开发者中解放出来。
The GC's engine determines the best time to perform a garbage collection. When the garbage collector performs a collection, it checks for objects in the managed heap that are no longer being used by the application and performs the necessary operations (automatically releases the memory allocated) to reclaim their memory.
What this means, is that in Delphi for .Net, you can *safely* create an object without "freeing" it.
Every application uses resources of one sort or another: memory buffers, files, database connections, network resources, and so on.
GC is not "all mighty" - if you are using "external" resources, like database connections or network resources, you are still responsible for freeing "unmanaged" (or external) resources. The framework can track when the unmanaged resource needs to be terminated, but it does not have information on how to terminate the resource and free up the memory. In order to force the developer to free its resources, any class that operates on "unmanaged" resources must implement the Dispose (made it public) method of the IDisposable interface. In general, your implementation of the Dispose method should release all the resources that an object owns (with a call to "inherited Dispose").
Finalize, IDisposable.Dispose, Free, Destroy?
Every class in the .NET Framework inherits a method called Finalize. The bad news is that the GC calls the Finalize method (and therefore if overridden it should be protected) when the memory for the object is about to be freed. Since the method is called by the garbage collector, you have no control over when it is called.
The good news is that in Delphi for .NET, all objects implicitly implement IDisposable and redirect calls to Dispose to the Destroy destructor. This means that you do not need to implement Dispose yourself ... you can safely continue freeing resources (for objects/classes you develop) in the object's destructor "Destroy" method.
Should you call AnObject.Free?
Recall that, in Win32, calling "Free" automatically calls the destructor if the object reference is not nil. In .Net, on the on the hand, a call to Free is (as stated above) redirected to Dispose which in turn calls your destructor.
What this means is that when you call Free in .Net, you actually call IDisposable.Dispose.
This is the Delphi for .Net version of the "Free" method (from source code):
procedure TObjectHelper.Free; begin if (Self <> nil) and (Self is IDisposable) then begin if Assigned(VCLFreeNotify) then VCLFreeNotify(Self); (Self as IDisposable).Dispose; end; end; |
What this tells us, is that to free "unmanaged" (external) resources, you can safely continue using "Free" inside try-finally blocks (since you do not *generally* know whether an object you create uses "unmanaged" resources).
Conclusion: Delphi code you write remains the same, but the compiler implementation changes significantly. You do not need to be frightened of calling "Free", nor should you change all your Win32 projects you are about to pre-compile using VCL.Net!
Note: be sure to read the "Memory Management Issues on the .NET Platform" topic in the Delphi for .Net Help system.