垃圾收集的正确位置,处理模式中的文件类型

问题描述 投票:1回答:1

现在,我的同事之间就需要在哪里处理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;
}
c# dispose unmanaged
1个回答
1
投票

只需仔细阅读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

© www.soinside.com 2019 - 2024. All rights reserved.