现在,我的同事之间就需要在哪里处理C#文件类型进行了辩论。 (https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose)
查看下面的代码,当前File.Delete在if(dispose)部分中,在该部分中被视为托管对象。有些人认为它需要不在循环中,并且需要放置在非托管对象中。
~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)
块之外使用any现有对托管对象的引用。在您的示例中,tempFilePaths
似乎是IEnumerable<string>
类型的字段/属性,它是受管理对象(现有引用)。因此,访问/使用它的唯一正确位置是在if (disposing)
块内部。原因
if (disposing)
之外的代码在调用公共Dispose()
方法时以及在终结器调用时运行both。终结器将在特殊的终结器线程上调用。不保证-在终结器调用时-tempFilePaths
完全可用。尽管对象引用由您的类实例保存,但它可能已经由GC收集了。这就是决赛选手的工作方式。如果与团队讨论时想要更多背景知识和更多争论,请仔细阅读Eric Lippert(前C#编译器团队成员)有关定稿器的博客文章:
When everything you know is wrong, part oneWhen everything you know is wrong, part two