c# - 垃圾收集的正确位置处置模式中的文件类型

标签 c# dispose unmanaged

现在我的同事之间就需要在哪里处理 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/

相关文章:

c# - 保护用户的云服务 API key 安全

c# - 使用 hang-fire 和 ASP.NET Core 发送每日摘要电子邮件

sharepoint - 我应该处理这个 SPWeb 吗?

c# - 使用 Microsoft.Practices.EnterpriseLibrary.Data 时要丢弃什么?

c# - Dispose 方法中有多少工作?

.net - 是否可以同时制作同一 C++ 程序集的托管和非托管版本?

c# - 错误 : returns void, return 关键字后面不能跟对象表达式

c# - 在 WPF 中,PreviewTextInput 是否总是只给出一个字符?

c# - native C++ dll 的 C++/CLI 包装器

c++ - 在 Visual Studio 2008 中引用另一个非托管 C++ 项目中的非托管 C++ 项目