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

时间:2020-12-14 21:32:44

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? 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()方法吗?在我看来,只有对象的所有者/创建者在完成对象而不是对象本身时才应该调用Dispose()。

It's an .asmx web method that calls Dispose() on itself when it's done. (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. 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.

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

[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服务代理类?

8 个解决方案

#1


32  

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对象,而不是对象本身。

#2


4  

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

对我来说这是一种红旗/代码味道

#3


2  

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.

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

#4


1  

There are no technical restrictions on what a Dispose method is allowed to do. The only thing special about it is that Dispose gets called in certain constructs (foreach, using). Because of that, Dispose might reasonably be used to flag an object as no-longer-useable, especially if the call is idempotent.

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

I would not use it for this purpose however, because of the accepted semantics of 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的语义被接受,我不会将它用于此目的。如果我想在对象本身内部标记一个不再可用的对象,那么我将创建一个可以被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方法,并确保您不会意外地破坏任何偏离常见模式的代码。

#5


0  

Just remove it, but take care to dispose it in all object that call it.

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

#6


0  

Technically yes, if that "method" is the finaliser and you are implementing the Finalise and IDisposable pattern as specified by Microsoft.

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

#7


0  

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. 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:

虽然.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

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; 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. 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.

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

#8


0  

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).

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

#1


32  

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对象,而不是对象本身。

#2


4  

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

对我来说这是一种红旗/代码味道

#3


2  

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.

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

#4


1  

There are no technical restrictions on what a Dispose method is allowed to do. The only thing special about it is that Dispose gets called in certain constructs (foreach, using). Because of that, Dispose might reasonably be used to flag an object as no-longer-useable, especially if the call is idempotent.

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

I would not use it for this purpose however, because of the accepted semantics of 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的语义被接受,我不会将它用于此目的。如果我想在对象本身内部标记一个不再可用的对象,那么我将创建一个可以被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方法,并确保您不会意外地破坏任何偏离常见模式的代码。

#5


0  

Just remove it, but take care to dispose it in all object that call it.

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

#6


0  

Technically yes, if that "method" is the finaliser and you are implementing the Finalise and IDisposable pattern as specified by Microsoft.

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

#7


0  

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. 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:

虽然.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

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; 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. 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.

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

#8


0  

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).

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