Подтвердить что ты не робот

Как проверить, был ли объект удален в С#

Возможный дубликат:
Как определить, установлена ​​ли ссылка на IDisposable?

Есть ли способ проверить, был ли объект удален иным, чем

try
{
    myObj.CallRandomMethod();
} catch (ObjectDisposedException e)
{
    // now I know object has been disposed
}

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

4b9b3361

Ответ 1

Хорошим способом является вывод из TcpClient и переопределение метода Disposing (bool):

class MyClient : TcpClient {
    public bool IsDead { get; set; }
    protected override void Dispose(bool disposing) {
        IsDead = true;
        base.Dispose(disposing);
    }
}

Что не будет работать, если другой код создал экземпляр. Тогда вам придется сделать что-то отчаянное, как использование Reflection, чтобы получить значение частного члена m_CleanedUp. Или поймайте исключение.

Честно говоря, никто из них, скорее всего, не достигнет хороших результатов. Вы действительно хотели написать TCP-порт. Но вы не будете, этот багги-код, который вы не можете контролировать, теперь контролирует ваш код. Вы увеличили влияние ошибки. Говорить с владельцем этого кода и работать над чем-то, безусловно, лучшим решением.

Ответ 2

Надежное решение ловит ObjectDisposedException.

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

Другим подходом может быть раскрытие гипотетического события Disposed (например this), который используется для уведомления об утилизационном объекте для каждого интересующего объекта, но это может быть затруднено для планирования в зависимости от дизайна программного обеспечения.

Ответ 3

Если вы не уверены, был ли объект удален или нет, вы должны вызвать сам метод Dispose, а не методы, такие как Close. Хотя структура не гарантирует, что метод Dispose должен выполняться без исключений, даже если объект ранее был удален, это общий шаблон и, насколько мне известно, реализован на всех одноразовых объектах в рамках.

Типичный шаблон для Dispose, согласно Microsoft:

public void Dispose() 
{
    Dispose(true);

    // Use SupressFinalize in case a subclass
    // of this type implements a finalizer.
    GC.SuppressFinalize(this);      
}

protected virtual void Dispose(bool disposing)
{
    // If you need thread safety, use a lock around these 
    // operations, as well as in your methods that use the resource.
    if (!_disposed)
    {
        if (disposing) {
            if (_resource != null)
                _resource.Dispose();
                Console.WriteLine("Object disposed.");
        }

        // Indicate that the instance has been disposed.
        _resource = null;
        _disposed = true;   
    }
}

Обратите внимание на проверку _disposed. Если бы вы вызвали метод Dispose, реализующий этот шаблон, вы могли бы вызвать Dispose столько раз, сколько захотите, не попав в исключения.