在this MSDN资源之后,代码
using System;
class BaseClass : IDisposable
{
// Flag: Has Dispose already been called?
bool disposed = false;
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing) {
// Free any other managed objects here.
//
}
// Free any unmanaged objects here.
//
disposed = true;
}
~BaseClass()
{
Dispose(false);
}
}
关于释放托管资源/对象的评论。
据我所知,垃圾收集器可以做到这一点,但是在这里实际编写这样的代码是否是一种好习惯,因此我的意思是将对象的引用指向null?
我相信这是“处置”托管资源时可以做的最好的事情,尽管您在此过程中什么也做不了,因为垃圾收集器将进行实际的繁重工作,而不是将其引用设置为null。 (垃圾收集器会注意到未使用包含这些对象/资源的类本身(没有引用),这使该任务变得毫无意义)
谢谢!
答案 0 :(得分:2)
请注意,处置对象不会释放已分配的内存。这只是一种指示对象可能拥有的非托管资源的使用终止的方式。
例如,如果您的对象拥有一个非托管资源(例如TCP套接字),则可以让垃圾收集器在运行时结束所有操作,但是该套接字在此之前可能一直处于活动状态,从而导致以下情况:您在给定的时间有许多打开的连接,而服务器拒绝了新的连接。
当您有SqlConnection时会发生这种情况。当您调用Dispose时,它实际上不会关闭SqlServer的套接字,而是将连接返回到可以重用的池中。如果不处理SqlConnection,则在并发系统上,有一段时间这些对象是要进行垃圾收集的候选对象,但是由于它们仍然保持连接,因此有时您将与SqlServer建立过多的连接,并且可能会开始拒绝新的。
与SqlTransaction类似的东西。如果在调用Commit或Rollback之前引发了异常,并且从未调用过Dispose,则该连接可能会锁定表,页面等上的锁,从而导致其他连接的性能下降。
即使调用Dispose,SqlConnection对象仍在内存中,等待收集,但是由于实际的套接字已返回到池中而无法使用。实际上,如果您Dispose并调用其任何方法,它将抛出ObjectDisposedException,表明该对象不再可用。
实现IDisposable的对象或者拥有未使用的资源,或者拥有其他拥有未使用的资源的对象。因此,如果编写拥有SqlConnection的存储库类,则将需要实现级联Dispose调用。
答案 1 :(得分:0)
该方法的主体由两个代码块组成:
释放非托管资源的块。不管dispose参数的值如何,该块都会执行。
一个释放托管资源的条件块。如果dispose的值为true,则执行此块。它释放的托管资源可以包括:
实现IDisposable的托管对象。条件块可以 用于调用其Dispose实现。如果您使用了保险箱 包装非托管资源的句柄,应调用 SafeHandle.Dispose(Boolean)实现在这里。
消耗大量内存或稀缺资源的受管对象 资源。在Dispose方法中显式释放这些对象 释放它们的速度比不确定地回收它们的速度快 通过垃圾收集器。
因此,您当然应该释放所有也可以使用的托管对象,但是您可以可以释放所有使用大量内存或稀缺资源的托管对象。