现在我的同事之间就需要在哪里处理 C# 文件类型进行了争论。 (https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose)
查看下面的代码,当前 File.Delete 位于 if(diswriting) 部分,其中考虑将其用于托管对象。有些人认为它需要位于循环之外,并且需要放置非托管对象。
~someService() => Dispose(false);
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
GC.Collect();
}
bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (disposed)
{
return;
}
if (disposing)
{
// Dispose managed state (managed objects).
tempFilePaths?.ToList().ForEach(f =>
{
if (File.Exists(f))
{
File.Delete(f);
}
});
this._engine?.Dispose();
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
this._fields = null;
disposed = true;
}
最佳答案
请仔细阅读 IDisposable
模式来理解这些“部分”的含义以及它们何时被执行。
TL;DR
您不使用对 if (disposing)
之外的托管对象的任何现有引用。堵塞。在您的示例中,tempFilePaths
似乎是 IEnumerable<string>
的字段/属性类型是一个托管对象(现有引用)。因此,访问/使用它的唯一正确位置是 if (disposing)
内部。 block 。
原因
if (disposing)
之外的代码在调用公众 Dispose()
时运行两者方法以及由终结器调用时。
终结器将在特殊的终结器线程上调用。不保证 - 在终结器调用时 - tempFilePaths
将完全可用。尽管对象引用由您的类实例保存,但它可能已经被 GC 收集了。这就是终结器的工作原理。
如果您在与团队讨论时需要更多背景知识和更多参数,请仔细阅读 Eric Lippert(前 C# 编译器团队成员)关于终结器的博客文章:
When everything you know is wrong, part one
When everything you know is wrong, part two
关于c# - 垃圾收集的正确位置处置模式中的文件类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62071722/