处理模式中垃圾收集文件类型的正确位置
Right place to garbage collect File type in dispose pattern
现在我的同事之间就需要在何处处理 C# 文件类型争论不休。 (https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose)
查看下面的代码,目前 File.Delete 在 if(disposing) 部分中,它被认为是托管对象。有些人认为它需要在循环之外并且需要放置在非托管对象中。
~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
模式以了解这些 "sections" 的含义以及它们将在何时执行。
TL;DR
您不使用 any 对 if (disposing)
块之外的托管对象的现有引用。在您的示例中,tempFilePaths
似乎是 IEnumerable<string>
类型的 field/property,而 是 托管对象(现有引用)。因此,access/use 唯一正确的位置是在 if (disposing)
块内。
原因
if (disposing)
之外的代码在调用 public Dispose()
方法和被终结器调用时运行 both。
终结器将在特殊的终结器线程上调用。不能保证 - 在终结器调用时 - tempFilePaths
将完全可用。尽管对象引用由您的 class 实例持有,但它可能已经被 GC 收集了。这就是终结器的工作方式。
如果您想在与您的团队讨论时获得更多背景知识和更多论据,请仔细阅读 Eric Lippert(前 C# 编译器团队成员)关于终结器的这些博文:
When everything you know is wrong, part one
When everything you know is wrong, part two
现在我的同事之间就需要在何处处理 C# 文件类型争论不休。 (https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose)
查看下面的代码,目前 File.Delete 在 if(disposing) 部分中,它被认为是托管对象。有些人认为它需要在循环之外并且需要放置在非托管对象中。
~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
模式以了解这些 "sections" 的含义以及它们将在何时执行。
TL;DR
您不使用 any 对 if (disposing)
块之外的托管对象的现有引用。在您的示例中,tempFilePaths
似乎是 IEnumerable<string>
类型的 field/property,而 是 托管对象(现有引用)。因此,access/use 唯一正确的位置是在 if (disposing)
块内。
原因
if (disposing)
之外的代码在调用 public Dispose()
方法和被终结器调用时运行 both。
终结器将在特殊的终结器线程上调用。不能保证 - 在终结器调用时 - tempFilePaths
将完全可用。尽管对象引用由您的 class 实例持有,但它可能已经被 GC 收集了。这就是终结器的工作方式。
如果您想在与您的团队讨论时获得更多背景知识和更多论据,请仔细阅读 Eric Lippert(前 C# 编译器团队成员)关于终结器的这些博文:
When everything you know is wrong, part one
When everything you know is wrong, part two