gpt4 book ai didi

c# - 在 C# 中使用 Finalize/Dispose 方法

转载 作者:IT王子 更新时间:2023-10-29 03:27:53 24 4
gpt4 key购买 nike

C# 2008

我已经研究了一段时间了,但我仍然对在代码中使用 finalize 和 dispose 方法感到困惑。我的问题如下:

  1. 我知道在处理非托管资源时我们只需要一个终结器。但是,如果有托管资源调用非托管资源,是否还需要实现终结器?

  2. 但是,如果我开发一个不直接或间接使用任何非托管资源的类,我是否应该实现 IDisposable 以允许该类的客户端使用 'using陈述'?

    实现 IDisposable 只是为了使您的类的客户端能够使用 using 语句是否可行?

    using(myClass objClass = new myClass())
    {
    // Do stuff here
    }
  3. 我在下面开发了这个简单的代码来演示 Finalize/dispose 的使用:

    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);
    }
    }

关于源码的问题:

  1. 这里我没有添加finalizer,通常finalizer会被GC调用,finalizer会调用Dispose。由于我没有终结器,我什么时候调用 Dispose 方法?是否必须调用它的类的客户端?

    所以我在示例中的类称为 NoGateway,客户端可以像这样使用和处理该类:

    using(NoGateway objNoGateway = new NoGateway())
    {
    // Do stuff here
    }

    是执行到using block 末尾时自动调用Dispose方法,还是需要客户端手动调用dispose方法?即

    NoGateway objNoGateway = new NoGateway();
    // Do stuff with object
    objNoGateway.Dispose(); // finished with it
  2. 我在我的 NoGateway 类中使用 WebClient 类。因为 WebClient 实现了 IDisposable 接口(interface),这是否意味着 WebClient 间接使用了非托管资源?是否有严格的规则来遵循这一点?我怎么知道一个类使用了非托管资源?

最佳答案

推荐的 IDisposable 模式是 here .在编写使用 IDisposable 的类时,通常应使用两种模式:

当实现不使用非托管资源的密封类时,您只需像普通接口(interface)实现一样实现 Dispose 方法:

public sealed class A : IDisposable
{
public void Dispose()
{
// get rid of managed resources, call Dispose on member variables...
}
}

当实现一个未密封的类时,这样做:

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 中声明终结器;如果您有实际的非托管资源要处理,您应该只实现终结器。 CLR 处理可终结对象的方式与处理非可终结对象的方式不同,即使调用了 SuppressFinalize

因此,除非万不得已,否则您不应该声明终结器,但是您可以为您的类的继承者提供一个 Hook ,以调用您的 Dispose 并在他们直接使用非托管资源时自行实现终结器:

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 和 friend 不算在内,因为它们声明了自己的终结器),那么不要实现终结器,因为 GC 处理可终结的以不同的方式分类,即使您稍后抑制终结器也是如此。另请注意,即使 B 没有终结器,它仍会调用 SuppressFinalize 以正确处理任何实现终结器的子类。

当一个类实现了 IDisposable 接口(interface)时,这意味着某处有一些非托管资源,当您使用完该类后应该将其清除。实际资源封装在类中;您不需要明确删除它们。只需调用 Dispose() 或将类包装在 using(...) {} 中即可确保在必要时清除任何非托管资源。

关于c# - 在 C# 中使用 Finalize/Dispose 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/898828/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com