问题描述
C# 2008
我已经研究了一段时间了,我仍然对代码中使用 finalize 和 dispose 方法感到困惑.我的问题如下:
I have been working on this for a while now, and I am still confused about the use of finalize and dispose methods in code. My questions are below:
我知道在处理非托管资源时我们只需要一个终结器.但是,如果有托管资源调用非托管资源,还需要实现终结器吗?
I know that we only need a finalizer while disposing unmanaged resources. However, if there are managed resources that make calls to unmanaged resources, would it still need to implement a finalizer?
但是,如果我开发一个不直接或间接使用任何非托管资源的类,我是否应该实现 IDisposable
以允许该类的客户端使用使用陈述'?
However, if I develop a class that doesn't use any unmanaged resource - directly or indirectly, should I implement the IDisposable
to allow the clients of that class to use the 'using statement'?
实现 IDisposable 只是为了让您的类的客户能够使用 using 语句是否可行?
Would it be feasible to implement IDisposable just to enable clients of your class to use the using statement?
using(myClass objClass = new myClass())
{
// Do stuff here
}
我在下面开发了这个简单的代码来演示 Finalize/dispose 的使用:
I have developed this simple code below to demonstrate the Finalize/dispose use:
public class NoGateway : IDisposable
{
private WebClient wc = null;
public NoGateway()
{
wc = new WebClient();
wc.DownloadStringCompleted += wc_DownloadStringCompleted;
}
// Start the Async call to find if NoGateway is true or false
public void NoGatewayStatus()
{
// Start the Async's download
// Do other work here
wc.DownloadStringAsync(new Uri(www.xxxx.xxx));
}
private void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
// Do work here
}
// Dispose of the NoGateway object
public void Dispose()
{
wc.DownloadStringCompleted -= wc_DownloadStringCompleted;
wc.Dispose();
GC.SuppressFinalize(this);
}
}
关于源代码的问题:
这里我没有添加终结器,一般情况下终结器会被GC调用,终结器会调用Dispose.由于我没有终结器,我什么时候调用 Dispose 方法?是该类的客户端必须调用它吗?
Here I have not added the finalizer, and normally the finalizer will be called by the GC, and the finalizer will call the Dispose. As I don't have the finalizer, when do I call the Dispose method? Is it the client of the class that has to call it?
所以我在这个例子中的类叫做 NoGateway,客户端可以像这样使用和处理这个类:
So my class in the example is called NoGateway and the client could use and dispose of the class like this:
using(NoGateway objNoGateway = new NoGateway())
{
// Do stuff here
}
执行到 using 块结束时会自动调用 Dispose 方法,还是客户端必须手动调用 dispose 方法?即
Would the Dispose method be automatically called when execution reaches the end of the using block, or does the client have to manually call the dispose method? i.e.
NoGateway objNoGateway = new NoGateway();
// Do stuff with object
objNoGateway.Dispose(); // finished with it
我在我的 NoGateway
类中使用了 WebClient
类.因为WebClient
实现了IDisposable
接口,这是否意味着WebClient
间接使用了非托管资源?是否有严格的规则来遵循这一点?我怎么知道一个类使用了非托管资源?
I am using the WebClient
class in my NoGateway
class. Because WebClient
implements the IDisposable
interface, does this mean that WebClient
indirectly uses unmanaged resources? Is there a hard and fast rule to follow this? How do I know that a class uses unmanaged resources?
推荐答案
推荐的 IDisposable 模式是 此处.在编写使用 IDisposable 的类时,通常应该使用两种模式:
The recommended IDisposable pattern is here. When programming a class that uses IDisposable, generally you should use two patterns:
在实现不使用非托管资源的密封类时,您只需像普通接口实现一样实现 Dispose 方法:
When implementing a sealed class that doesn't use unmanaged resources, you simply implement a Dispose method as with normal interface implementations:
public sealed class A : IDisposable
{
public void Dispose()
{
// get rid of managed resources, call Dispose on member variables...
}
}
当实现一个未密封的类时,这样做:
When implementing an unsealed class, do it like this:
public class B : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// get rid of managed resources
}
// get rid of unmanaged resources
}
// only if you use unmanaged resources directly in B
//~B()
//{
// Dispose(false);
//}
}
请注意,我没有在 B
中声明终结器;如果您有实际的非托管资源要处理,您应该只实现终结器.即使调用了 SuppressFinalize
,CLR 对可终结对象的处理方式与不可终结对象的处理方式不同.
Notice that I haven't declared a finalizer in B
; you should only implement a finalizer if you have actual unmanaged resources to dispose. The CLR deals with finalizable objects differently to non-finalizable objects, even if SuppressFinalize
is called.
因此,除非必须,否则您不应该声明终结器,但是您可以为类的继承者提供一个钩子来调用您的 Dispose
并在他们直接使用非托管资源时自己实现终结器:
So, you shouldn't declare a finalizer unless you have to, but you give inheritors of your class a hook to call your Dispose
and implement a finalizer themselves if they use unmanaged resources directly:
public class C : B
{
private IntPtr m_Handle;
protected override void Dispose(bool disposing)
{
if (disposing)
{
// get rid of managed resources
}
ReleaseHandle(m_Handle);
base.Dispose(disposing);
}
~C() {
Dispose(false);
}
}
如果您不直接使用非托管资源(SafeHandle
和朋友不计算在内,因为他们声明了自己的终结器),则不要实现终结器,因为 GC 处理的是 finalizable不同的类,即使您后来取消了终结器.另请注意,即使 B
没有终结器,它仍会调用 SuppressFinalize
以正确处理任何实现终结器的子类.
If you're not using unmanaged resources directly (SafeHandle
and friends doesn't count, as they declare their own finalizers), then don't implement a finalizer, as the GC deals with finalizable classes differently, even if you later suppress the finalizer. Also note that, even though B
doesn't have a finalizer, it still calls SuppressFinalize
to correctly deal with any subclasses that do implement a finalizer.
当一个类实现了 IDisposable 接口时,这意味着在您使用完该类后,某些地方应该删除一些非托管资源.实际资源被封装在类中;您不需要明确删除它们.只需调用 Dispose()
或将类包装在 using(...) {}
中即可确保根据需要删除任何非托管资源.
When a class implements the IDisposable interface, it means that somewhere there are some unmanaged resources that should be got rid of when you've finished using the class. The actual resources are encapsulated within the classes; you don't need to explicitly delete them. Simply calling Dispose()
or wrapping the class in a using(...) {}
will make sure any unmanaged resources are got rid of as necessary.
这篇关于C#中Finalize/Dispose方法的使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!