当我在两个相互依赖的IDisposable
对象之间有循环依赖关系,并且还应该相互传播处理时,我应该如何最好地避免Dispose()
方法中的无限递归产生StackOverflowException
呢?
我最初的猜测是保存并判断对象是否已经在调用堆栈中调用了它的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;
}
}
}
不过,我没有在快速的谷歌搜索中找到这样的实现,所以我想知道做、保存和好是不是都可以.
程序输出为:
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