.Net / C#对象应该自己调用Dispose()吗?

时间:2011-02-18 18:41:46

标签: c# .net web-services dispose idisposable

以下是一位同事撰写的示例代码。这对我来说显然是错的,但我想检查一下。对象是否应该从其自己的方法中调用自己的 Dispose()方法?在我看来,只有对象的所有者/创建者在完成对象而不是对象本身时才应该调用 Dispose()

这是一个.asmx网络方法,当它完成时会调用 Dispose()。 (事实上​​,这是一个Web方法可能是一般问题的偶然事实。)在我们的代码库中,我们有时在其他Web服务的方法中实例化Web服务类,然后调用它们上的方法。如果我的代码执行此操作来调用此方法,则该方法返回时该对象是toast,并且我无法再使用该对象。

[WebMethod]
public string MyWebMethod()
{
    try
    {
        return doSomething();
    }
    catch(Exception exception)
    {
        return string.Empty;
    }
    finally
    {
        Dispose(true);
    }
}

更新: 找到了一些相关的链接:

Do I need to dispose a web service reference in ASP.NET?

Dispose a Web Service Proxy class?

8 个答案:

答案 0 :(得分:34)

当然,这不是一个好的表现。调用者应该决定何时使用IDisposable对象,而不是对象本身。

答案 1 :(得分:4)

如果我在其中一个项目中看到过,我会问为什么,我99.9999%确定我会删除它

对我而言,这是一种red flag / code smells

答案 2 :(得分:3)

执行“自我处置”操作的正当理由非常少。 线程是我最常使用的。

我有几个“发射并忘记”线程的应用程序。 使用这种方法可以使对象自行处理。

这有助于在没有线程管理器进程的情况下保持环境清洁。

答案 3 :(得分:1)

对Dispose方法允许执行的操作没有技术限制。唯一特别之处在于Dispose在某些构造中被调用(foreachusing)。因此,可以合理地使用Dispose将对象标记为不再可用,特别是如果调用是幂等的。

然而,由于Dispose的语义被接受,我不会将它用于此目的。如果我想在对象本身内标记一个不再可用的对象,那么我将创建一个可以被Dispose或任何其他地方调用的MarkUnuseable()方法。

通过将对Dispose的调用限制为普遍接受的模式,您可以放心地更改所有类中的Dispose方法,并确保不会意外地破坏任何偏离公共模式的代码。

答案 4 :(得分:0)

只需删除它,但要注意将其丢弃在所有调用它的对象中。

答案 5 :(得分:0)

技术上是的,如果该“方法”是终结者,并且您正在实施Microsoft指定的Finalise and IDisposable pattern

答案 6 :(得分:0)

虽然.Net对象通常不会自己调用Dispose,但有时候在对象中运行的代码可能是最后一个期望使用它的东西。举个简单的例子,如果Dispose方法可以处理部分构造的对象的清理,那么构造函数的编码可能会很有用,如下所示:

Sub New()
  Dim OK As Boolean = False
  Try
    ... do Stuff
    OK = True
  Finally
    If Not OK Then Me.Dispose
  End Try
End Sub

如果构造函数在没有返回的情况下抛出异常,那么部分构造的对象(将被放弃)将是唯一能够获得必要清理的信息和动力的对象。如果它不能确保及时处理,那么别的什么都不会。

关于你的特定代码片段,模式有点不寻常,但它看起来有点像套接字从一个线程传递到另一个线程的方式。有一个调用返回一个字节数组并使一个Socket无效;该字节数组可以在另一个线程中用于创建一个新的Socket实例,该实例接管由另一个Socket建立的通信流。请注意,有关open socket的数据实际上是一个非托管资源,但它不能很好地包含在带有终结器的对象中,因为它经常会被传递给垃圾收集器无法看到的东西。

答案 7 :(得分:0)

没有!这是意外行为,违反了最佳做法指南。永远不要做任何未被发现的事情。您的对象应该只执行维护其状态所需的操作,同时保护调用者的对象的完整性。调用者将决定何时完成(或者如果没有别的话)。