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


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

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

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

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

4 57

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. Или поймать исключение.

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

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

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