如何在 C# 中处理循环 Dispose()

问题描述 投票:0回答:1

当我在两个相互依赖的

IDisposable
对象之间存在循环依赖并且也应该相互传播处理时,我应该如何最好地避免
StackOverflowException
方法中的无限递归?
我最初的猜测是保存并检查对象是否已经在调用堆栈中调用了它的 

Dispose()

方法并在这种情况下提前退出,就像我在示例实现中所做的那样:

Dispose()

虽然我在快速谷歌搜索中没有找到这样的实现,所以我想知道是否可以做,保存和一切都很好。

程序输出为:

using CircularDispose; using JetBrains.Annotations; Example a = new(nameof(a)); Example b = new(nameof(b)); a.Other = b; b.Other = a; Console.WriteLine("Start"); a.Dispose(); Console.WriteLine($"{nameof(a)} is disposed: {a.IsDisposed}"); Console.WriteLine($"{nameof(b)} is disposed: {b.IsDisposed}"); Console.WriteLine("Finished"); namespace CircularDispose { [PublicAPI] public class Example : IDisposable { private bool _isDisposing; private string _name; public Example? Other { get; set; } public bool IsDisposed { get; private set; } public Example(string name) => _name = name; public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } private void Dispose(bool disposing) { Console.WriteLine($"{_name}.{nameof(Dispose)}({disposing}) was called"); if (!_isDisposing && !IsDisposed) { _isDisposing = true; if (disposing) { DisposeManagedResources(); } DisposeUnmanagedResources(); IsDisposed = true; } } ~Example() { Dispose(false); } [PublicAPI] protected virtual void DisposeUnmanagedResources() { // dispose unmanaged resources } [PublicAPI] protected virtual void DisposeManagedResources() { Other?.Dispose(); Other = null; } } }


c# stack-overflow dispose circular-dependency
1个回答
0
投票
Start a.Dispose(True) was called b.Dispose(True) was called a.Dispose(True) was called a is disposed: True b is disposed: True Finished

字段:

_isDisposing

如果内存消耗是一个问题(例如,因为您有 
很多

类的实例),一个技巧是重用 private void Dispose(bool disposing) { Console.WriteLine($"{_name}.{nameof(Dispose)}({disposing}) was called"); if (!IsDisposed) { IsDisposed = true; if (disposing) { DisposeManagedResources(); } DisposeUnmanagedResources(); } } 部分中已经使用的现有变量,例如您的

DisposeManagedResources()
变量案件。如果它为 null,则 Dispose 已被调用(或没有必要)。
Other
永远不应该是循环的,因为那样你会接触到一些不是非托管资源的东西,所以它也可能在
DisposeUnmanagedResources()
.
 之外
    

© www.soinside.com 2019 - 2024. All rights reserved.