如何检查对象是否已在C#中处理

时间:2010-08-11 10:51:45

标签: c# .net dispose

  

可能重复:
  How does one tell if an IDisposable object reference is disposed?

是否有方法检查对象是否已被置于不同的

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

在我的情况下,我正在使用具有TcpClient方法的Close()类来处理对象,这可能发生在我无法控制的代码段中。在这种情况下,我希望有更好的解决方案然后捕获异常。

4 个答案:

答案 0 :(得分:31)

一个好方法是从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端口。但你不会,你无法控制的错误代码现在可以控制你的代码了。你增加了bug的影响。与该代码的所有者交谈并解决问题是迄今为止最好的解决方案。

编辑:一个反思例子:

using System.Reflection;
public static bool SocketIsDisposed(Socket s)
{
   BindingFlags bfIsDisposed = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetProperty;
   // Retrieve a FieldInfo instance corresponding to the field
   PropertyInfo field = s.GetType().GetProperty("CleanedUp", bfIsDisposed);
   // Retrieve the value of the field, and cast as necessary
   return (bool)field.GetValue(s, null);
}

答案 1 :(得分:26)

可靠的解决方案是捕获ObjectDisposedException。

编写Dispose方法的重写实现的解决方案不起作用,因为在调用Dispose方法的线程和访问该对象的线程之间存在竞争条件:在检查了假设的IsDisposed属性之后,该对象可以真正处理掉,抛出异常。

另一种方法可能是暴露一个假设事件Disposed(如this),它用于向每个感兴趣的对象通知处置对象,但根据软件设计,这可能难以计划。

答案 2 :(得分:16)

如果您不确定对象是否已被处置,则应调用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,而不会遇到异常。

答案 3 :(得分:0)

最佳做法是使用本地布尔字段自己实现它: http://www.niedermann.dk/2009/06/18/BestPracticeDisposePatternC.aspx