Използване на шаблон за еднократна употреба за почистване на класове членове на IDispose

Част от шаблона за еднократна употреба включва следния метод.

protected virtual void Dispose(bool disposing)
{
    if (!disposed)
    {
        if (disposing)
        {
            // TODO: dispose managed state (managed objects).
        }

        // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
        // TODO: set large fields to null.
        disposed = true;
    }
}

Този метод има различна обработка за почистване на управлявани и неуправлявани ресурси. Но какво ще стане, ако искам да изчистя член на клас, който имплементира IDisposable?

Обикновено не знам дали този член почиства управлявани или неуправлявани ресурси. Така че, ако искам моят Dispose метод да изчисти член на клас, който имплементира IDisposable, бих ли извикал Dispose() на този член в управляваните или неуправляваните секции в кода по-горе?


person Jonathan Wood    schedule 10.08.2015    source източник
comment
Може да искате да разгледате Fody.Janitor. Той автоматично ще приложи това за вас.   -  person Aron    schedule 10.08.2015


Отговори (2)


Трябва да извикате Dispose в управляваната секция (т.е. само когато disposing е true).

Част от указанията в Изхвърляне на шаблон под Указания за проектиране на рамка е:

Булевият параметър disposing показва дали методът е бил извикан от внедряването IDisposable.Dispose или от финализатора. Реализацията Dispose(bool) трябва да проверява параметъра преди достъп до други референтни обекти [...]. Такива обекти трябва да бъдат достъпни само когато методът е извикан от внедряването IDisposable.Dispose (когато параметърът за изхвърляне е равен на true). Ако методът е извикан от финализатора (изхвърлянето е невярно), не трябва да се осъществява достъп до други обекти. Причината е, че обектите се финализират в непредсказуем ред и така те или някоя от техните зависимости може вече да са финализирани.

Друг полезен ресурс е Имплементиране на метод за изхвърляне

person Frank Boyne    schedule 10.08.2015

Стандартният начин за изхвърляне на членовете на класа, който имплементира IDisposable, е като този:

public class Foo : IDisposable
{
    // MemoryStream implements IDisposable
    private readonly Stream _stream = new MemoryStream();

    private bool _disposed;

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (_disposed)
        {
            return;
        }

        if (disposing)
        {
            _stream.Dispose();
        }

        _disposed = true;
    }
}

За пояснение, почистването на управлявани ресурси означава, че самият ресурс прилага IDisposable (както MemoryStream прави по-горе). MemoryStream/Stream съдържа основния неуправляван ресурс и неговата логика за почистване вече е внедрена за вас. Няма нужда да почиствате неуправлявани ресурси в Foo.

person rexcfnghk    schedule 10.08.2015
comment
защо имате нужда от bool disposing, ако винаги е вярно? - person IronHide; 13.01.2020
comment
Тъй като за незапечатан клас можете да подадете false към Dispose(bool), когато производният клас има финализатор. Внедряване на метод Dispose - person rexcfnghk; 14.01.2020