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

jet*_*hro 68 .net c# dispose

可能重复:
如何判断是否处置了IDisposable对象引用?

有没有一种方法来检查对象是否已被处置不同

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

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

Han*_*ant 32

一个好方法是从TcpClient派生并覆盖Disposing(bool)方法:

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

如果其他代码创建了实例,那将无效.然后你将不得不做一些绝望的事情,比如使用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);
}
Run Code Online (Sandbox Code Playgroud)

  • dll 文件中的类怎么样? (2认同)

Luc*_*uca 30

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

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

另一种方法可能是暴露一个假设事件Disposed(像这样),用于向每个感兴趣的对象通知处理对象,但这可能难以根据软件设计进行规划.

  • 异常应该处理异常,而不是成为代码基础结构的一部分。使用它们是懒惰的,而不是它们的用途,这就是为什么原始帖子明确要求提供可靠的替代方案。 (8认同)

Rya*_*ner 16

如果您不确定对象是否已被处置,则应调用Dispose方法本身而不是方法Close.虽然框架不能保证Dispose方法必须在没有异常的情况下运行,即使该对象先前已被处理过,但这是一种常见的模式,而且我的知识是在框架中的所有一次性对象上实现的.

对于典型的模式Dispose,按照微软:

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;   
    }
}
Run Code Online (Sandbox Code Playgroud)

注意检查_disposed.如果您要调用Dispose实现此模式的方法,则可以根据需要多次调用Dispose,而不会遇到异常.

  • 虽然框架本身没有给出任何保证,但是`IDisposable`的文档说:*"如果对象的`Dispose`方法被多次调用,对象必须忽略第一个之后的所有调用.对象不能如果多次调用`Dispose`方法,则抛出异常.除了`Dispose`之外的实例方法可以在资源已经处理时抛出`ObjectDisposedException`.**http://msdn.microsoft.com/en-us/library /system.idisposable.dispose.aspx (3认同)
  • 这没用.该成员是私人的. (2认同)