Поиск…


замечания

  • Клиенты класса, реализующие IDisposable могут быть уверены, что они вызовут метод Dispose когда они будут завершены с использованием объекта. В CLR ничего не найдено, что непосредственно ищет объекты для метода Dispose для вызова.

  • Нет необходимости реализовывать финализатор, если ваш объект содержит только управляемые ресурсы. Обязательно вызывайте Dispose во всех объектах, которые использует ваш класс, когда вы реализуете свой собственный метод Dispose .

  • Рекомендуется сделать класс безопасным для нескольких вызовов Dispose , хотя в идеале его следует вызывать только один раз. Этого можно добиться, добавив в свой класс private bool переменную private bool и установив значение true когда был запущен метод Dispose .

В классе, который содержит только управляемые ресурсы

Управляемые ресурсы - это ресурсы, которые сообщают сборщики мусора времени выполнения и находятся под контролем. Существует много классов, доступных в BCL, например, таких как SqlConnection который является классом-оболочкой для неуправляемого ресурса. Эти классы уже реализуют интерфейс IDisposable - это зависит от вашего кода, чтобы очистить их, когда вы закончите.

Нет необходимости реализовывать финализатор, если ваш класс содержит только управляемые ресурсы.

public class ObjectWithManagedResourcesOnly : IDisposable
{
    private SqlConnection sqlConnection = new SqlConnection();

    public void Dispose()
    {
        sqlConnection.Dispose();
    }
}

В классе с управляемыми и неуправляемыми ресурсами

Важно, чтобы финализация игнорировала управляемые ресурсы. Финализатор работает в другом потоке - возможно, что управляемые объекты больше не существуют к моменту завершения финализатора. Реализация защищенного метода Dispose(bool) является обычной практикой для обеспечения того, что управляемые ресурсы не имеют метода Dispose вызванного из финализатора.

public class ManagedAndUnmanagedObject : IDisposable
{
    private SqlConnection sqlConnection = new SqlConnection();
    private UnmanagedHandle unmanagedHandle = Win32.SomeUnmanagedResource();
    private bool disposed;

    public void Dispose()
    {
        Dispose(true); // client called dispose
        GC.SuppressFinalize(this); // tell the GC to not execute the Finalizer
    }

    protected virtual void Dispose(bool disposeManaged)
    {
        if (!disposed)
        {
            if (disposeManaged)
            {
                if (sqlConnection != null)
                {
                    sqlConnection.Dispose();
                }
            }

            unmanagedHandle.Release();

            disposed = true;
        }
    }

    ~ManagedAndUnmanagedObject()
    {
        Dispose(false);
    }
}

IDisposable, Dispose

.NET Framework определяет интерфейс для типов, требующих метода сбрасывания:

public interface IDisposable
{
  void Dispose();
}

Dispose() в основном используется для очистки ресурсов, например, неуправляемых ссылок. Однако также может быть полезно принудительно распоряжаться другими ресурсами, даже если они управляются. Вместо того, чтобы ждать, пока GC в конечном итоге также очистит ваше соединение с базой данных, вы можете убедиться, что это сделано в вашей собственной реализации Dispose() .

public void Dispose()
{
   if (null != this.CurrentDatabaseConnection)
   {
       this.CurrentDatabaseConnection.Dispose();
       this.CurrentDatabaseConnection = null;
   }
}

Когда вам нужно напрямую обращаться к неуправляемым ресурсам, таким как неуправляемые указатели или ресурсы win32, создайте класс, наследующий от SafeHandle и используйте соглашения / инструменты этого класса для этого.

В унаследованном классе с управляемыми ресурсами

Довольно часто можно создать класс, который реализует IDisposable , а затем выводит классы, которые также содержат управляемые ресурсы. Рекомендуется пометить метод Dispose ключевым словом virtual чтобы клиенты могли очищать любые ресурсы, которыми они могут владеть.

public class Parent : IDisposable
{
    private ManagedResource parentManagedResource = new ManagedResource();

    public virtual void Dispose()
    {
        if (parentManagedResource != null)
        {
            parentManagedResource.Dispose();
        }
    }
}

public class Child : Parent
{
    private ManagedResource childManagedResource = new ManagedResource();

    public override void Dispose()
    {
        if (childManagedResource != null)
        {
            childManagedResource.Dispose();
        }
        //clean up the parent's resources
        base.Dispose();
    }
}

использование ключевого слова

Когда объект реализует интерфейс IDisposable , он может быть создан в синтаксисе using :

using (var foo = new Foo())
{
    // do foo stuff
} // when it reaches here foo.Dispose() will get called

public class Foo : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine("dispose called");
    }
}

Просмотреть демоверсию

using синтаксического сахара для блока try/finally ; приведенное выше использование будет примерно переводить:

{
    var foo = new Foo();
    try
    {
        // do foo stuff
    }
    finally
    {
        if (foo != null)
            ((IDisposable)foo).Dispose();
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow