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

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

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

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

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

4 ответов


хороший способ-вывести из TcpClient и переопределить метод Disposing (bool):

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

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

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


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

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

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


если вы не уверены, был ли объект удален или нет, вы должны вызвать 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 столько раз, сколько хотите, не нажимая исключений.


Лучшая практика говорит, чтобы реализовать его самостоятельно, используя местные логическое поле: http://www.niedermann.dk/2009/06/18/BestPracticeDisposePatternC.aspx