C#中如何在Dispose()方法中配置托管资源?我知道Dispose()是针对非托管资源的,当不再需要该资源时,它应该在不等待垃圾收集器完成该对象的情况下处理该资源。但是,它会在处理对象时抑制垃圾收集器的完成(GC.SuppressFinalize(this);在下面的代码中)。这意味着如果对象包含托管资源,我们也必须处理它,因为垃圾收集器不会清理它。在下面的示例代码中(来自MSDN),“Component”是一个托管资源,我们为这个资源调用dispose()(component.Dispose())。我的问题是,我们如何为作为托管资源的Component类实现此方法?我们是否应该使用Collect()之类的东西来戳垃圾收集器来清理这部分?任何想法将不胜感激。谢谢。以下是我正在查看的来自MSDN的代码:usingSystem;使用System.ComponentModel;//下面的示例演示如何创建//实现IDisposable接口和IDisposable.Dispose方法的资源类。publicclassDisposeExample{//实现IDisposable的基类。//通过实施IDisposable,您宣布//这种类型的实例分配稀缺资源。publicclassMyResource:IDisposable{//指向外部非托管资源的指针。私有IntPtr句柄;//此类使用的其他托管资源。私有组件组件=新组件();//跟踪是否调用了Dispose。私人布尔处置=假;//类的构造函数。publicMyResource(IntPtrhandle){this.handle=handle;}//实现IDisposable。//不要让这个方法成为虚拟的。//派生类不应重写此方法。publicvoidDispose(){Dispose(真);//这个对象会被th清理掉e处理方法。//因此,您应该调用GC.SupressFinalize//将此对象从终结队列中移除//并防止此对象的终结代码//再次执行。GC.SuppressFinalize(这个);}//Dispose(booldisposing)在两个不同的场景中执行。//如果disposing等于true,则该方法已被直接调用//或由用户代码间接调用。托管和非托管资源//可以被释放。//如果disposing等于false,则该方法已由//运行时从终结器内部调用,您不应引用//其他对象。只能释放非托管资源。privatevoidDispose(booldisposing){//检查Dispose是否已经被调用。if(!this.disposed){//如果disposing等于true,则释放所有托管资源//和非托管资源。if(disposing){//处理托管资源。组件.Dispose();}//调用适当的方法来清理//非托管资源he关于。//如果disposing为false,//仅执行以下代码。关闭句柄(句柄);句柄=IntPtr。零;//注意处理已经完成。处置=真;}}//使用互操作来调用必要的方法//以清理非托管资源。[System.Runtime.InteropServices.DllImport("Kernel32")]privateexternstaticBooleanCloseHandle(IntPtrhandle);//对终结代码使用C#析构函数语法。//此析构函数仅在Dispose方法//未被调用时运行。//它让你的基类有机会完成。//不要在从此类派生的类型中提供析构函数。~MyResource(){//不要在这里重新创建Dispose清理代码。//就可读性和可维护性而言,调用Dispose(false)是最佳的。处置(假);}}publicstaticvoidMain(){//在此处插入代码以创建//并使用MyResource对象。这意味着如果对象包含托管资源,我们也必须处理它,因为垃圾收集器不会清理它,这是错误的。垃圾收集器仍会清理您的托管资源。终结器也严格用于清理非托管资源,因此SuppressFinalize()调用不会对您造成任何伤害。由于您是IDisposable模式的新手,我会预料到您的下一个困惑点:编写终结器。在C#中,只有在处理全新的非托管资源时才应编写终结器。因此,如果您有一个类将System.Data.SqlClient.SqlConnection类型包装为数据访问层的一部分,则不应为该类型编写终结器,因为您仍在处理相同类型的底层非托管资源:sqlserver数据库连接。此资源的终结器已由基本SqlConnection类型处理。另一方面,如果您正在为一种全新的数据库引擎构建ADO.Net提供程序,您将需要在您的连接类中实现终结器,因为您以前从未这样做过。这种一次性模式令人困惑。这里有一个更好的方法:第1步。创建一个一次性类来封装您拥有的每个非托管资源。这应该是非常罕见的,大多数人没有非托管资源需要清理。这个类只关心(pdf)它的非托管资源并且应该有一个终结器。实现看起来像这样:publicclassNativeDisposable:IDisposable{publicvoidDispose(){CleanUpNativeResource();GC.SuppressFinalize(这个);}protectedvirtualvoidCleanUpNativeResource(){//...}~NativeDisposable(){CleanUpNativeResource();}//...IntPtr_nativeResource;}Step2.当班级持有其他一次性班级时,创建一个一次性班级。这很容易实现,你不需要终结器。在Dispose方法中,只需对另一个一次性调用Dispose。在这种情况下,您不关心非托管资源:publicclassManagedDisposable:IDisposable{//...publicvirtualvoidDispose(){_otherDisposable.Dispose();}IDisposable_otherDisposable;示例中的“组件”可能是其中之一,具体取决于它是否封装了非托管资源,或者它是否仅由其他一次性资源组成。另请注意,抑制终结器并不意味着您阻止垃圾收集器清理您的实例;这只是意味着当垃圾收集器在您的实例上运行时,它不会调用为其定义的终结器。也许更清晰一点。GC.SuppressFinalize(this)只影响this指针引用的对象,而不影响对象的任何成员。也就是说,SuppressFinalize不会以递归方式应用于对象的成员。当垃圾收集器回收Disposed对象的内存时,很可能不会有对该对象字段的活动引用。由于您没有在对象的所有字段上调用??GC.SuppressFinalize,垃圾收集器将在这些对象上调用finalize方法(如果存在)。当它完成时,一切都取决于运行时,通常你应该让它做它的事情。对不起,如果我误解了你的问题!!,但如果你的类只是引用其他托管类,并且不需要处理那些对这些对象的引用,那么你的类不一定需要实现IDisposable。以上是C#学习教程:如何在C#的Dispose()方法中配置托管资源?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
