Правильное место для сбора мусора Тип файла в шаблоне удаления - PullRequest
2 голосов
/ 28 мая 2020

Теперь между моими коллегами идет спор относительно того, где нужно обрабатывать тип файла C#. (https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/implementing-dispose)

Глядя на приведенный ниже код, в настоящее время File.Delete находится в разделе if (удаление), где он рассматривается для управляемых объектов. Некоторые люди считают, что он должен находиться за пределами l oop и должен быть местом для неуправляемых объектов.

~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;
}

1 Ответ

2 голосов
/ 28 мая 2020

Просто внимательно прочтите шаблон IDisposable, чтобы понять, что означают эти «разделы» и когда они будут выполнены.

TL; DR
Вы не используете любые существующие ссылки на управляемые объекты вне блока if (disposing). В вашем примере tempFilePaths кажется полем / свойством типа IEnumerable<string>, которое является управляемым объектом (существующей ссылкой). Таким образом, единственное правильное место для доступа / использования - внутри блока if (disposing).

Причина
Код за пределами if (disposing) запускается оба при вызове метода publi c Dispose() и при вызове финализатором.

Финализатор будет вызываться в специальном потоке финализатора. Не гарантируется, что во время вызова финализатора tempFilePaths будет вообще доступен. Он мог быть уже собран G C, несмотря на то, что ссылка на объект содержится в экземпляре вашего класса. Вот как работают финалисты.

Если вы хотите получить больше информации и больше аргументов во время обсуждения с вашей командой, пожалуйста, внимательно прочтите эти сообщения в блоге Эри c Липперта (бывшего члена команды C# компилятора) о финализаторы:

Когда все, что вы знаете, неверно, часть первая
Когда все, что вы знаете, неверно, часть вторая

...