【问题标题】:How to implement Dispose on object creates other disposables如何在对象上实现 Dispose 创建其他一次性用品
【发布时间】:2018-11-20 10:11:02
【问题描述】:

给定以下课程:

public class MyDisposableContainer : IDisposable
{
    readonly List<IDisposable> _chidlren = new List<IDisposable>();

    public void Add() => _children.Add(new FileSystemWachter());
}

我不确定应该如何实现 Disposable 接口。

要么:

 public void Dispose() => _children.ForEach(item => item.Dispose());

public void Dispose()
{
    // Dispose of unmanaged resources.
    Dispose(true);
    // Suppress finalization.
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
        _children.ForEach(item => item.Dispose());
    }
}

在我的例子中,孩子是使用一些非托管资源的 FileSystemWatcher,所以我猜它与终结器一起实现了一次性模式。

我想,第二种更长的方法是不必要的,因为它 Dispose(true) 只会在显式 Dispose() 调用时被调用。我说的对吗?

【问题讨论】:

  • 你是对的,但请记住,如果你创建一个派生自MyDisposableContainer 的类,你的实现就会失败。你有两个选择让你的班级sealed 或实现一个终结器和完整的Dispose 模式。
  • 啊,好吧,有道理。但是,是否有必要在基类中实现终结器(在我的情况下为 MyDisposableContainer)?不知何故,我不明白为什么当其他类继承自它时它是必要的
  • 假设你需要一个终结器在 99.9% 的情况下都是错误的。它也在这里,FSW 已经有了自己的终结器。
  • 基类中不需要终结器。考虑使用终结器仅用于当您需要某种保证以释放由于任何原因无法以其他方式释放的资源时(消费者未正确使用DisposeDispose 方法中引发的异常等) .由于 CLR 负责托管资源,因此受此类场景影响的唯一资源是非托管资源。
  • @DmytroMukalov:如果您在答案中总结了 cmets,您会很高兴

标签: c# dispose idisposable


【解决方案1】:

所以简短的回答是:是的,你可以使用简单的形式

public void Dispose() =&gt; _children.ForEach(item =&gt; item.Dispose());

在你的情况下。

扩展形式

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

protected virtual void Dispose(bool disposing)
{
    if (disposing)
    {
       ...
    }
}

basic dispose pattern 的基本实现在这里有点多余,但建议将其作为未来可能通过继承扩展类的良好方式和基础(除非它是密封的)。

更长的答案意味着澄清与处置相关的可能情景和最佳实践。对象销毁过程处理两种类型的资源管理和管理。托管资源可以被 GC 成功处理,所以我们通常不应该为此烦恼太多,而非托管资源释放是调用代码的责任,因为 GC 无法跟踪它们的分配和取消分配。 IDisposable 接口的目的是解决应该在某些对象或对象层次结构中处理非托管资源解除分配的情况。现在至于可能的情况:

  • 如果您的类直接保留非托管资源,则建议使用带终结器的扩展finalizable dispose pattern,以涵盖外部消费者不正确使用类的情况或通过@987654327 获得有保证的资源取消分配的特殊情况@ 或终结器;
  • 如果您的类拥有其他 IDisposable 但不直接拥有非托管资源,则推荐的方法是使用不带终结器的 basic dispose pattern

关于销毁责任分离的一些注释,因为它在 cmets 中弹出。每个类都应该负责清楚地处理它直接保留的那些资源的释放。它不应该试图以任何其他方式处理底层对象的发布场景,而不是使用他们公开暴露的合约,即通过IDisposable 或任何其他接口,并且不应该在这些公共合约之外做出任何假设。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-08
    • 2022-06-10
    • 1970-01-01
    • 2015-03-31
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多