Гарантируется ли одноразовый объект в моем классе iDisposable из памяти? - PullRequest
0 голосов
/ 02 марта 2020

Учитывая следующий класс:

public sealed class DistributedLock : IDisposable
{
    private IRedLock Lock { get; }
    private bool _disposed;

    public DistributedLock(string lockKey, TimeSpan expiry)
    {
        Lock = RedLockController.GetConnection().CreateLock(lockKey, expiry);
    }

    private void Dispose(bool disposing)
    {
        if (_disposed)
            return;

        if (disposing)
        {
            if (Lock != null)
            {
                Lock.Dispose();
            }
        }

        _disposed = true;
    }

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

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

Где IRedLock реализует iDisposable, и я использую вышеупомянутый класс следующим образом:

using(new DistributedLock("SomeKey"))
{
    ... do something
}

Будет DistributedLock и содержащийся IRedLock класс будет освобожден из памяти при любых обстоятельствах?

1 Ответ

1 голос
/ 02 марта 2020

IDisposable относится к управлению ресурсами , кроме памяти : такие как дескрипторы GDI, сокеты, файловые дескрипторы и т. Д. c. Это не мешает сборщику мусора. Следовательно, IDisposable поможет вам освободить память только в двух ситуациях:

  1. Если ваш тип IRedLock получает неуправляемую память, например, через стороннюю библиотеку или код unsafe .
  2. Если ваш метод Dispose() очищает ссылки на этот объект из других объектов, чтобы быть уверенным, что объект будет иметь право на сборку мусора, если это не могло быть иначе (как это происходит, например, с событием обработчики).

Если ни один из этих двух вариантов не применяется (и ничто в приведенном выше коде не указывает на их применение), вы ничего не получите от IDisposable в плане управления памятью.

То, что вы можете получить из IDisposable в этом коде, является лучшим механизмом для освобождения соединения, на которое намекается эта строка:

Lock = RedLockController.GetConnection().CreateLock(lockKey, expiry);

Однако вам, вероятно, не нужны связанные с ним финализации. Вы только оборачиваете что-то еще, что уже имеет финализатор, и поэтому вы можете использовать более простой шаблон IDisposable без дополнительной сложности:

public sealed class DistributedLock : IDisposable
{
    private IRedLock Lock { get; }

    public DistributedLock(string lockKey, TimeSpan expiry)
    {
        Lock = RedLockController.GetConnection().CreateLock(lockKey, expiry);
    }

    public void Dispose()
    {
        Lock?.Dispose();
    }
}
...