gpt4 book ai didi

c# - Microsoft IDisposable 模式真的正确吗?

转载 作者:行者123 更新时间:2023-12-05 02:32:46 25 4
gpt4 key购买 nike

我多次偶然发现 Microsoft 推荐的实现 IDisposable 模式的方法,它甚至作为灯图标菜单中的“实现接口(interface)”选项出现在 Visual Studio 中。它看起来像这样:

// Override only if 'Dispose(bool disposing)' has code to free unmanaged resources
~Foo() {
// Do not change this code.
Dispose(calledByFinalizer: true);
}
public void Dispose() {
// Do not change this code.
Dispose(calledByFinalizer: false);
GC.SuppressFinalize(this);
}
// Put cleanup code here
protected virtual void Dispose(bool calledByFinalizer) {
if (_disposed) return;

if (!calledByFinalizer) { /* dispose managed objects */ }

/* free unmanaged resources and set large fields to null */

_disposed = true;
}

我稍微重构了建议的代码(因为 Dispose(bool disposing) 会伤人的大脑,而嵌套 if 会伤人的眼睛)。

但是我还有一些疑问:

  1. 假定该方法将被调用一次。那为什么_disposed = true放在方法的末尾而不是开头呢?如果IDisposable.Dispose()是从不同线程调用的,那么它们都可以绕过if (_disposed) return;检查,实际执行两次方法体。为什么不这样做:
    if (_disposed) return;
else _disposed = true;
  1. 为什么 protected virtual void Dispose(bool disposing) 被标记为 virtual?任何派生类都无法访问 _disposed 字段,并且很容易破坏其行为。我们只能将派生类可以在不调用 base.Dispose() 的情况下执行任何操作的可选部分标记为 virtual:
~Foo() => FreeUnmanagedResources();

public void Dispose() {
if (_disposed) return;
else _disposed = true;

DisposeManagedObjects();
FreeUnmanagedResources();

GC.SuppressFinalize(this);
}

protected virtual void DisposeManagedObjects() { }
protected virtual void FreeUnmanagedResources() { }

最佳答案

该模式是正确的,但假设了最坏的情况,您还必须实现终结器。也就是说,如果您需要一个终结器,您还必须遵循整个模式。然而……

您通常根本不需要终结器。

只有在为非托管资源创建原始托管包装器时才需要终结器。

例如,假设您创建了一个全新的、前所未见的数据库系统。您希望为这种新型数据库提供 .Net ADO 提供程序,包括连接(它将继承自 Dbconnection)。这里的底层网络操作将是一个非托管资源,并且还没有一个终结器来在你的继承树中的任何地方释放它们。因此,您必须实现自己的终结器。

另一方面,如果您正在为您的应用程序创建一个包装器对象来管理与现有数据库类型的连接——只是重新包装(包装或继承)现有的 SqlConnection、OleDbConnection、MySqlConnection 等——那么您仍然应该实现 IDisposable ,但是已经为非托管资源提供了一个终结器,您不需要编写另一个。

事实证明,当您没有终结器时,您可以安全地从记录的 IDisposable 模式中删除大量代码。

关于c# - Microsoft IDisposable 模式真的正确吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71150572/

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