简体   繁体   English

.Net / C#对象是否应自行调用Dispose()?

[英]Should a .Net/C# object call Dispose() on itself?

Below is some sample code written by a colleague. 下面是一位同事编写的一些示例代码。 This seems obviously wrong to me but I wanted to check. 这似乎对我来说显然是错误的,但我想检查一下。 Should an object call its own Dispose() method from within one of its own methods? 对象应该从自己的方法之一中调用自己的Dispose()方法吗? It seems to me that only the owner/creator of the object should call Dispose() when it's done with the object and not the object itself. 在我看来,在处理完对象之后,只有对象的所有者/创建者才应调用Dispose() ,而不是对象本身。

It's an .asmx web method that calls Dispose() on itself when it's done. 这是一个.asmx网络方法,完成后会自行对其调用Dispose() (The fact that it's a web method is probably incidental to the question in general.) In our code base we sometimes instantiate web service classes within methods of other web services and then call methods on them. (这实际上是一个Web方法,实际上通常是这个问题附带的。)在我们的代码库中,有时我们会在其他Web服务的方法中实例化Web服务类,然后在它们上调用方法。 If my code does that to call this method, the object is toast when the method returns and I can't really use the object any more. 如果我的代码执行此操作来调用此方法,则该对象将在方法返回时吐司,并且我无法再使用该对象了。

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

UPDATE: Found a few links that are related: 更新:找到了一些相关的链接:

Do I need to dispose a web service reference in ASP.NET? 我是否需要在ASP.NET中处理Web服务引用?

Dispose a Web Service Proxy class? 处置Web服务代理类?

For sure it's not a good prartice. 当然,这不是一个好办法。 The caller should decide when he is finished using the IDisposable object, not an object itself. 调用方应决定何时使用IDisposable对象(而不是对象本身)完成操作。

if I ever see that in one of my projects, I would ask why and I'm 99.9999% sure that i would remove it anyway 如果我在自己的一个项目中看到它,我会问为什么,并且我99.9999%的确定我会删除它

for me this is a kind of red flag / code smells 对我来说,这是一种红旗/代码的气味

There are very few valid reasons to perform a "Self Disposing" action. 很少有有效的理由执行“自处置”操作。 Threading is the one I use more than not. 线程是我经常使用的线程。

I have several applications that "fire and forget" threads. 我有几个“解雇”线程的应用程序。 Using this methodology allow the object to self dispose. 使用这种方法可以使对象自行处置。

This helps keep the environment clean without a threading manager process. 这有助于在没有线程管理器进程的情况下保持环境的清洁。

There are no technical restrictions on what a Dispose method is allowed to do. 对于允许的Dispose方法没有技术限制。 The only thing special about it is that Dispose gets called in certain constructs ( foreach , using ). 唯一的特别之处是Dispose在某些构造中被调用( foreachusing )。 Because of that, Dispose might reasonably be used to flag an object as no-longer-useable, especially if the call is idempotent. 因此,可以合理地使用Dispose将对象标记为不再可用,尤其是在调用是幂等的情况下。

I would not use it for this purpose however, because of the accepted semantics of Dispose. 但是,由于Dispose接受了语义,因此我不会将其用于此目的。 If I wanted to mark an object as no-longer-useable from within the class itself, then I would create a MarkUnuseable() method that could be called by Dispose or any other place. 如果我想从类本身内部将对象标记为不可再使用,那么我将创建一个可由Dispose或其他任何地方调用的MarkUnuseable()方法。

By restricting the calls to Dispose to the commonly accepted patterns, you buy the ability to make changes to the Dispose methods in all of your classes with confidence that you will not unexpectedly break any code that deviates from the common pattern. 通过将对Dispose的调用限制为普遍接受的模式,可以购买到对所有类中的Dispose方法进行更改的能力,并确信您不会意外破坏任何偏离公共模式的代码。

只需将其删除,但要小心将其放置在所有调用它的对象中。

从技术上讲,是的,如果该“方法”是终结器,并且您正在实现Microsoft指定的Finalize和IDisposable模式

While a .Net object would not normally call Dispose on itself, there are times when code running within an object may be the last thing that expects to be using it. 虽然.Net对象通常不会自行调用Dispose,但有时在对象中运行的代码可能是最后一个希望使用它的东西。 As a simple example, if a Dispose method can handle the cleanup of a partially-constructed object, it may be useful to have a constructor coded something like the following: 举一个简单的例子,如果Dispose方法可以处理部分构造的对象的清理,那么构造一个类似以下代码的构造函数可能会很有用:

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

If the constructor is going to throw an exception without returning, then the partially-constructed object, which is slated for abandonment, will be the only thing that will ever have the information and impetus to do the necessary cleanup. 如果构造函数将抛出异常而没有返回,那么将被废弃的部分构造的对象将是唯一具有信息和动力进行必要清理的对象。 If it doesn't take care of ensuring a timely Dispose, nothing else will. 如果没有确保及时处置,则别无所求。

With regard to your particular piece of code, the pattern is somewhat unusual, but it looks somewhat like the way a socket can get passed from one thread to another. 对于您的特定代码段,该模式有些不寻常,但看起来有点像套接字可以从一个线程传递到另一个线程的方式。 There's a call which returns an array of bytes and invalidates a Socket; 有一个调用返回一个字节数组并使Socket无效; that array of bytes can be used in another thread to create a new Socket instance which takes over the communications stream established by the other Socket. 该字节数组可以在另一个线程中使用,以创建一个新的Socket实例,该实例接管另一个Socket建立的通信流。 Note that the data regarding the open socket is effectively an unmanaged resource, but it can't very well be wrapped in an object with a finalizer because it's often going to be handed off to something the garbage-collector can't see. 请注意,有关打开套接字的数据实际上是非托管资源,但不能很好地将其包装在带有终结器的对象中,因为它通常会传递给垃圾收集器无法看到的内容。

No! 没有! It is unexpected behavior and breaks the best practices guidelines. 这是意外行为,并且违反了最佳做法准则。 Never do anything that is unexpeceted. 切勿做任何意外的事情。 Your object should only do what is needed to maintain it's state while protecting the integrity of the object for the caller. 您的对象应仅执行维护其状态所需的操作,同时为调用者​​保护对象的完整性。 The caller will decide when it's done (or the GC if nothing else). 调用方将决定完成的时间(如果没有其他操作,则由GC决定)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM