问题在下面的这个代码段中标了出来,请回答一下(1,2,3):public class Resource : IDisposable
{
private IntPtr nativeResource = Marhsal.AllocHGlobal(100);
private AnotherResource managedResource = new AnotherResource(); // Dispose() calls Dispose(true)
public void Dispose()
{
/*
1:下面的代码为什么一定要调用Dispose(true),而不是直接把代码放到这里执行?或为什么一定是Dispose(true)
*/
Dispose(true);
GC.SuppressFinalize(this);
}
// NOTE: Leave out the finalizer altogether if this class doesn't 
// own unmanaged resources itself, but leave the other methods
// exactly as they are. 
~Resource()
{
/*
2:下面的代码为什么不是调用Dispose(true)而调用了Dispose(false)?
*/
// Finalizer calls Dispose(false)
Dispose(false);
}
// The bulk of the clean-up code is implemented in Dispose(bool)
protected virtual void Dispose(bool disposing)
{
/*
3:下面的代码为什么要用disposing做了分支,nativeResource为什么不太disposing分支中
而managedResource却在disposing分支中?
*/
if (disposing)
{
// free managed resources
if (managedResource != null)
{
managedResource.Dispose();
managedResource = null;
}
}
// free native resources if there are any.
if (nativeResource != IntPtr.Zero)
{
Marshal.FreeHGlobal(nativeResource);
nativeResource = IntPtr.Zero;
}
}
}

解决方案 »

  1.   

    http://www.cnblogs.com/caomao/archive/2006/10/03/152505.html
      

  2.   

    呵呵,这个问题还蛮有回答的价值的。微软在VS2003的帮助中可以说是讲得非常的含糊,不过在VS2005的帮助中终于多了几句话,阐明了析构函数的使用时机。好像有点儿偏题?一点儿也不。在C#中,或者说在CLR中,析构函数并不是原来在C++中的意义,因为所有的非托管资源都会被GC回收。所以析构函数的唯一用处就是释放非托管资源。如果在你的类的对象中,直接使用了非托管资源,就必须写析构函数。这就是析构函数的使用时机。
    因为如果你不写析构函数,那么你使用的非托管资源将永远不能被释放。举个例子,你写了一个类,直接使用了非托管资源。它创建了一个对象,然后,这个对象被抛弃了,而你永远也不能知道这个对象被抛弃的事实。然后,GC尝试回收你这个对象。再然后,恐怖的事情发生了,你的对象所占用的内存空间被回收,它所携带的所有关于非托管资源的信息被GC弄丢了。这个时候,神仙也不能释放那个非托管资源了。所以GC提供了一个机制来避免这种事情的发生,这就是我们今天看到的析构函数。明白了这一点,IDisposable也就好解释了。
    析构函数是释放非托管资源的最后一道屏障,没有析构函数,非托管资源就可能永远不能被释放。
    但我们有时候会想要手动释放非托管资源,这个时候微软提供了另一套机制,就是IDisposable接口和相关的语法。当然,IDisposable并不仅仅用于释放非托管资源,如果你愿意,大可以用它来释放托管资源。
    这也就是.NET Framework代码中大量充斥两个Dispose方法的原因。
    微软约定:
    Dispose( bool disposing );//其中的disposing参数指明是否释放托管资源。这里牵出另一个问题
    就是在析构函数中是绝对不能引用任何托管资源的。
    我们知道GC的原理,它是通过对象的引用类搜索垃圾对象的。
    也就是说,当一个对象成为垃圾时,它所引用的所有托管对象都可能已经是垃圾了(因为它本身不是垃圾,那么它所引用的就都不是垃圾)。而析构函数是延迟执行的,就是说GC会先回收同一个批次的没有析构函数的对象并调用析构函数,再回收调用析构函数后的对象。
    所以说,当析构函数被执行的时候,这个对象所引用的东西可能都已经被回收了……
      

  3.   

    结论:
    1、如果你的类不会直接使用托管资源,就不要写析构函数。
    2、如果你间接使用了托管资源,譬如说你内部包含了一个SqlConnection。你可以实现IDisposable接口,但只需要写一个Dispose方法调用SqlConnection的Dispose方法即可,千万不要写析构函数来调用。
    3、如果你的类直接使用了托管资源,就照上面的代码写即可。
      

  4.   

    在C#中,或者说在CLR中,析构函数并不是原来在C++中的意义,因为所有的非托管资源都会被GC回收。所以析构函数的唯一用处就是释放非托管资源。更正为:在C#中,或者说在CLR中,析构函数并不是原来在C++中的意义,因为所有的托管资源都会被GC回收。所以析构函数的唯一用处就是释放非托管资源。
      

  5.   

    如果是我引用的都是实现了IDisposable接口的对象,那么我是不是就不用写构造函数,也不用写Dispose(bool disposing)了,只用写Dispose()就可以了呢?
      

  6.   

    如果是我引用的都是实现了IDisposable接口的对象,那么我是不是就不用写构造函数,也不用写Dispose(bool disposing)了,只用写Dispose()就可以了呢?是的,不过这里还有一个职责的问题,即我创建的资源,我有责任销毁,不是我创建的,我没责任销毁。
    什么样的资源才算是非托管的次源呢?应该说是通过各种手段用非托管代码分配的资源……