我应该将 C# 的 using 语句与哪些类一起使用?
我已阅读并相信我理解 C# 的 using
语句的作用(如果我错了,请纠正我):将 IDisposable 对象初始化为只读,范围有限(using< /代码> 块)。我知道您可以在
using
之前进行初始化,这不会限制范围,但建议不要这样做:
http://msdn.microsoft.com/en-us/library/yh598w02.aspx
我并不总是关注哪些类是哪些类的子类。我不太确定哪些类继承自 IDisposable。我不仅好奇在 using
语句中可以使用哪些类,而且我的同事希望在 using
块中找到哪些类? 应该哪些类位于 using
块中?另外,不使用 using
块并且不调用 Dispose 真的有什么问题吗?仅仅与内存有关还是与稳定性有关?
I've read and I believe I understand what C#'s using
statement does (please correct me if I'm wrong): Initializes an IDisposable object as read only to a limited scope (the using
block). I know you can initialize before the using
and that doesn't limit the scope, but that is advised against here:
http://msdn.microsoft.com/en-us/library/yh598w02.aspx
I'm not always paying attention to what classes are subclasses of what. I'm not too sure what classes inherit from IDisposable. I'm not just curious what classes can be used in a using
statement, but what classes would my coworkers expect to find in a using
block? What classes should be in a using
block? Also, is there really anything wrong with not using a using
block and not calling Dispose? Is it just about memory or also stability?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(10)
严格来说,任何实现了 IDisposable 且其范围仅限于该函数的对象都应该位于 using 块内。 IDisposable 接口的存在是为了允许处理非托管资源(数据库连接、文件句柄、窗口句柄等)的类及时、确定地处理这些资源。
一般来说,在类中使用 IDisposable 对象有以下三种方式:
using
的情况下。System.IO.StreamWriter
IDisposable
对象的可用生命周期超出了单个方法调用的范围,并且可能超出了对象的生命周期。在这种情况下,必须由其他人负责调用Dispose
。第一种情况是您最常遇到的情况,这就是
using
块存在的原因。它负责确保即使在发生异常的情况下也会处理该对象。一些示例:
没有实现 IDisposable 的类的详尽列表,因为该列表相当大,并且充满了您可能永远不会遇到的类。想想这个类做什么;它是否打开某种需要关闭的连接或文件?一般来说,它是否获取某种需要释放的资源?如果是这样,它可能会实现它。在基本层面上,如果编译器允许您将其包含在
using
中,那么它就实现了IDisposable
。至于不调用
Dispose
的后果,不用考虑。 调用 Dispose。确实,防御标准是,如果您的类直接使用非托管资源,那么您应该定义一个终结器,该终结器将在您的对象被收集并且有人未能调用它时调用 dispose,但是不应该是一个设计选择。据我所知,曾经如此。Strictly speaking, any object that implements
IDisposable
and whose scope is limited to that function should be within ausing
block. TheIDisposable
interface exists to allow classes that deal with unmanaged resources (database connections, file handles, window handles, etc.) to dispose of these resources in a timely, deterministic fashion.There are, in general, three ways in which an
IDisposable
object is used within a class:using
can (and should) be used.Stream
and needs to use it over the lifetime of the object. In this case, your class should implementIDisposable
itself and dispose of the object(s) that you own when your ownDispose
method is called. An example of this would be something likeSystem.IO.StreamWriter
IDisposable
object's usable lifetime is beyond the scope of a single method call, and may be beyond the lifetime of your object. In this case, someone else must be responsible for callingDispose
.The first case is the most common that you'll encounter, which is why the
using
block exists. It takes care of ensuring that the object will be disposed of, even in the case of an exception.Some examples:
There's no exhaustive list of classes that implement
IDisposable
, as that list would be fairly large and filled with classes that you'll likely never encounter. Think about what the class does; does it open some sort of connection or file that needs to be closed? In general, does it acquire some kind of resource that needs to be released? If so, it probably implements it. At a basic level, if the compiler allows you to enclose it inusing
, then it implementsIDisposable
.As to the consequences of not calling
Dispose
, don't consider it. Call Dispose. True, the defensive standard is that if your class uses unmanaged resources directly, then you should define a finalizer that will call dispose in the event that your object is collected and someone has failed to call it, but that should not be a design choice. Ever, as far as I'm aware.这与记忆无关。它与其他资源有关,例如文件句柄、数据库连接等。
基本上,如果一个类实现了 IDisposable,那么这是一个信号,表明您应该在完成后处理它,因为它可能具有非托管资源,这会导致留在周围会很昂贵。 (例如,您的连接池可能会耗尽连接,或者文件句柄将保持打开状态,从而阻止另一段代码再次打开同一文件)。
It's not about memory. It's about other resources such as file handles, database connections etc.
Basically if a class implements
IDisposable
, that's a signal that you should dispose of it when you're done, because it may have unmanaged resources which would be expensive to leave around. (e.g. your connection pool may run out of connections, or a file handle will stay open, preventing another piece of code from opening the same file again).您应该始终在任何实现
IDisposable
的类上调用Dispose
,这可以通过using
块轻松完成。这不仅仅是记忆的问题。这也不仅仅是资源的问题。这是关于正确性的。
StreamWriter 是一个著名的例子。微软甚至开发了MDA来捕获程序员忘记的一些情况调用
Dispose
。这不仅仅是内存或资源:在 StreamWriter 示例中,正在写入的文件可能会被截断。有一次,我不得不追踪一个令人讨厌的错误(实际上是在我老板的代码中),其中数据库事务被回滚......事实证明,原因是
Dispose
没有被调用,因此当进程退出时它试图向磁盘提交太多内容(进程退出期间终结器超时)。修复只是几个using
块。第三个示例:Microsoft 的托管 ESENT 包装类具有“三层”处置方案,要求 以正确的顺序调用
Dispose
(最后是“外部”类)。因此,在三个现实世界的示例中,如果未正确调用
Dispose
,将会导致不正确的行为。其他类可能会表现出类似的行为。作为一般规则,您应该始终调用
Dispose
。You should always call
Dispose
on any class that implementsIDisposable
, and this is most easily done via ausing
block.This is not just about memory. This is also not just about resources. This is about correctness.
StreamWriter
is a famous example. Microsoft has even developed an MDA to catch some cases where programmers forgot to callDispose
. This is more than just memory or resources: in theStreamWriter
example, a file being written may be truncated.I had to track down a nasty bug one time (in my boss' code, actually), where a database transaction was being rolled back... turns out the cause was that
Dispose
wasn't being called, so it was trying to commit too much to disk when the process exited (there's a timeout for finalizers during process exit). The fix was just a fewusing
blocks.A third example: Microsoft's Managed ESENT wrapper classes have a "three tier" disposal scheme that requires
Dispose
to be called in the correct order ("outer" classes last).So, there are three real-world examples where incorrect behavior will result if
Dispose
is not called properly. Other classes may exibit similar behavior.As a general rule, you should always call
Dispose
.至少,所有使用非托管资源的类
At least, all class that used non managed resources
不使用 using 块并且不调用 Dispose 绝对是有很多错误的,您很可能会泄漏内存和/或资源。使用很方便,但您确实应该在从 IDisposable 派生的类的任何对象中调用 Dispose。
There is absolutely a lot wrong with not using a using block and not calling Dispose, you most likely will leak memory and / or resources. Using is a convenience, but you really should call Dispose in any object which class derives from IDisposable.
至于哪些类是一次性的,您可以自己探索智能感知,或者您只是从经验中学习。一些常见的包括
Image
及其子级,实际上大部分System.Drawing
命名空间、大量文件流、数据库连接等。至于何时应该调用它- 尽快地。如果您知道它是一次性的,并且知道您已经用完它,那么请调用 Dispose。
我相信许多实现 IDisposable 的 .NET 基类都实现了一次性模式,这意味着当垃圾收集器来获取它们时,它们将被正确地处理。但即便如此,您仍然应该在完成后处理掉一些东西,因为
此外,对于您自己编写的类,垃圾收集并不等于对非托管资源的正确处置 - 这是一个常见的混淆。一次性模式需要自己实现。
As far as what classes are disposable, you can probe intellisense yourself, or you'll just learn from experience. Some common ones include
Image
and its children, in fact most ofSystem.Drawing
namespace, plenty of file streams, database connections, etc.As far as when it should be called - as soon as possible. If you know it's disposable, and you know you're done with it, then call Dispose.
I believe many of the .NET base classes that implement
IDisposable
implement the disposable pattern, which means that they will be disposed of, properly, when the garbage collector comes to get them. But even so, you should still dispose of things when you're done, becauseAdditionally, for classes you write yourself, garbage collection does NOT equate to proper disposal for unmanaged resources - a common confusion. The disposable pattern needs to be implemented yourself.
类实现 IDisposable 的主要原因是释放非托管资源。当托管资源超出范围并且它认为合适时,垃圾收集器将释放它们,但它不了解非托管资源。调用Dispose方法将显式释放资源。
如果您不使用
using
块或调用Dispose
方法,那么您将遇到内存泄漏问题,进而可能导致稳定性问题。在处理实现
IDisposable
的类时,您应该始终使用using
块。尽管您可能更喜欢Try.. Catch.. Final
确保在finally
块中调用Dispose
,以便可以处理异常。The main reason a class would implement
IDisposable
is to release non managed resources. The garbage collector will release managed resources as they go out of scope and it sees fit, but it has no knowledge of non managed resources. Calling the Dispose method will explicitly release the resources.If you do not use a
using
block or call theDispose
method then you will have a problem with memory leakage, which in turn could cause stability issues.You should use a
using
block at all times when dealing with classes that implementIDisposable
. Although you may prefer aTry.. Catch.. Finally
ensuring that you callDispose
in thefinally
block so you can deal with exceptions.IDisposable 的目的是使与非托管资源(如文件、数据库或图形上下文)交互的对象能够自行清理。 using 语句是以下构造的便捷简写。
当然,问题是知道哪些对象实现 IDisposable...不幸的是,除了文档之外,没有自动方法可以知道。尽管我相信有一个 Fxcop 设置可以检查在使用之外使用的 IDisposables。
The purpose of IDisposable is to enable objects that interact with unmanaged resources (like files, databases, or graphics contexts) to clean up after themselves. A using statement is a convenient shorthand for the following construct
The problem of course is knowing which objects implement IDisposable...unfortunately there is no automated way to know besides the docs. Although I believe there is an Fxcop setting that will check for IDisposables used outside of a using.
您不必担心在 using 块下使用哪些类。如果您在 using 语句下使用的未实现 IDisposbale 那么它将向您显示红色/蓝色波浪。这样你就知道它缺少一次性的接口。据我使用过的几乎所有框架类都实现了 Idisposable。但在自定义类中,您需要实现
you need not to worry about using what classes under using blocks. If the you have used under using statement doesnot implements IDisposbale then it will show you red/blue wave. So that you can come to knwo that its lacking idisposable interface. And as far as i have used almost all classes of framework has Idisposable implemented. but in custom class , you need to implement
使用
using
调用的类有:还有很多其他类您也应该 Dispose,但上面的那些经常使用,经常使用。使用范围狭窄。
是的 - 不使用
using
和不调用dispose
会出现问题。经典的 Web 应用程序不会关闭与数据库的连接,在保持连接打开时有效地从数据库服务器中吸取资源。A ready-reckoner of classes to call with
using
is:There are many many more classes which you should also Dispose, but those above are frequently used, often in narrow usage scope.
Yes - there are issues with not using
using
and not callingdispose
. A classic is a web app which does not close its connections to a database, effectively sucking resources from the database server as it holds connections open.