gpt4 book ai didi

c# - 你如何防止 IDisposable 传播到你所有的类?

转载 作者:IT王子 更新时间:2023-10-29 03:32:51 26 4
gpt4 key购买 nike

从这些简单的类开始......

假设我有一组像这样的简单类:

class Bus
{
Driver busDriver = new Driver();
}

class Driver
{
Shoe[] shoes = { new Shoe(), new Shoe() };
}

class Shoe
{
Shoelace lace = new Shoelace();
}

class Shoelace
{
bool tied = false;
}

一个Bus有一个DriverDriver有两个Shoe,每个Shoe 有一个鞋带。都很傻。

向 Shoelace 添加一个 IDisposable 对象

后来我决定对 Shoelace 的某些操作可以是多线程的,因此我添加了一个 EventWaitHandle 供线程进行通信。所以 Shoelace 现在看起来像这样:

class Shoelace
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
// ... other stuff ..
}

在鞋带上实现 IDisposable

但是现在Microsoft's FxCop会提示:“在‘Shoelace’上实现 IDisposable,因为它创建了以下 IDisposable 类型的成员:‘EventWaitHandle’。”

好吧,我在 Shoelace 上实现了 IDisposable,我整洁的小类(class)变得一团糟:

class Shoelace : IDisposable
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;
private bool disposed = false;

public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}

~Shoelace()
{
Dispose(false);
}

protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
if (waitHandle != null)
{
waitHandle.Close();
waitHandle = null;
}
}
// No unmanaged resources to release otherwise they'd go here.
}
disposed = true;
}
}

或者(正如评论者所指出的)由于 Shoelace 本身没有非托管资源,我可能会使用更简单的 dispose 实现而不需要 Dispose(bool) 和 Destructor:

class Shoelace : IDisposable
{
private AutoResetEvent waitHandle = new AutoResetEvent(false);
bool tied = false;

public void Dispose()
{
if (waitHandle != null)
{
waitHandle.Close();
waitHandle = null;
}
GC.SuppressFinalize(this);
}
}

惊恐地看着 IDisposable 传播

没错,就是这样。但是现在 FxCop 会提示 Shoe 创建了一个 Shoelace,所以 Shoe 也必须是 IDisposable

并且 Driver 创建了 Shoe 所以 Driver 必须是 IDisposable。而 Bus 创建了 Driver 所以 Bus 必须是 IDisposable 等等。

我对 Shoelace 的小改动突然给我带来了很多工作,我的老板想知道为什么我需要结帐 Bus 才能对 Shoelace 进行更改

问题

您如何防止 IDisposable 的这种传播,但仍然确保正确处置您的非托管对象?

最佳答案

您无法真正“阻止”IDisposable 的传播。有些类需要释放,例如 AutoResetEvent,最有效的方法是在 Dispose() 方法中执行,以避免终结器的开销。但是这个方法必须以某种方式调用,所以就像在你的例子中封装或包含 IDisposable 的类必须处理这些,所以它们也必须是一次性的,等等。避免它的唯一方法是:

  • 尽可能避免使用 IDisposable 类,在单个位置锁定或等待事件,将昂贵的资源放在单个位置等
  • 仅在需要时创建它们并在之后立即释放它们(using 模式)

在某些情况下,IDisposable 可以忽略,因为它支持可选大小写。例如,WaitHandle 实现 IDisposable 以支持命名的 Mutex。如果未使用名称,则 Dispose 方法不执行任何操作。 MemoryStream 是另一个例子,它不使用系统资源,它的 Dispose 实现也什么都不做。仔细考虑是否正在使用非托管资源可能具有指导意义。因此可以检查 .net 库的可用源或使用反编译器。

关于c# - 你如何防止 IDisposable 传播到你所有的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/661815/

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