什么时候应该在C#中使用“使用”块?

是否有特定情况下我应该(或不应该)使用“使用”块:

using(SomeType t = new SomeType()){ ... } 

SomeType类实现IDisposable

有些物体在完成之后需要采取一些行动。 通常这是因为对象使用某种需要处理的资源。 例如,如果您有File类的文件对象,并且此对象从文件系统打开文件,则文件系统中的文件将需要再次closures。

如果你只是离开了文件对象,并忘记调用file.Close()它将不会被清理,直到垃圾收集器(GC)运行,并没有什么东西仍然使用文件对象。 垃圾收集器运行时应该留给公共语言运行时(CLR)来决定。 如果在完成文件后GC不运行很长一段时间,文件可能会长时间保持打开状态。 如果有很多的文件对象,或者某个东西想要打开一个文件,但是不能,因为你留下的文件对象仍然在附近,这会造成很大的问题。

为了解决这个问题,C#有了IDisposable接口。 这有一个名为Dispose的方法。 需要一些清理的类实现这个Dispose方法。 这为您提供了清理使用资源的任何对象的标准方法。 有很多类需要Dispose调用。 这个问题是代码被Dispose调用所覆盖,而且它们很难遵循,因为新对象的地方和调用Dispose来清理它们是不一样的。 所以,你必须仔细查看代码,并且非常小心地检查是否有在正确的位置调用Dispose。

为了解决这个问题,C#引入了'using'关键字。 你可以在你新build一个对象的地方放一个'using'关键字,这样可以确保Dispose会被你调用。 它保证Dispose将被调用,无论发生什么…即使在使用语句的内部引发了一个exception。

所以,当你想要确保一个分配资源的对象被清理时,你应该使用'using'。


使用只能用于在堆栈中声明的对象,即在函数中。 它不适用于声明为类成员的对象。 对他们来说,你必须自己调用Dispose。 您可能必须在您的类中实现Dispose,以便可以在任何需要它的成员对象上调用Dispose。


需要使用的通用对象调用它们是:文件,数据库连接,graphics对象,如钢笔和刷子。


有时也会在两个操作一起发生时使用。 例如,如果要在input代码块时写入日志语句,并在退出时写入一个可以使用的日志类,如下所示:

 using( Log log = new Log("Doing stuff") ) { // Stuff } 

log类的构造函数可以写出消息,Dispose方法也可以写出来。 如果Dispose方法没有被调用来确保“使用”被记住在“新日志”周围,实现终结器(〜Log)来断言。

每当types实现IDisposable ,除非你打算把它封装在try / catch块中,那么你也可以(取决于你喜欢什么样子)使用finally块。

当你有一个using声明时,我看到很多其他答案。 我想解决什么时候应该有具体的using说明:

如果您需要在当前函数的作用域之外使用您的对象,则不要using块。 很好的例子是返回数据库连接的工厂方法或需要返回一个datareader的方法。 在任何一种情况下,如果using语句创build对象,它将在返回的方法之前处理,因此在方法外部不可用。

现在,你仍然要确保这些对象被处置,所以你仍然可能想要一个using语句的地方。 只是不要将其包含在实际创build对象的方法中。 相反,您可以将函数调用本身封装在using语句中。

SomeType实现IDisposable时。

这是开发者对SomeType使用非托pipe资源需要清理的一个线索。

例:

  using(SqlConnection MyConnection = new SqlConnection("Connection string")) { MyConnection.Open(); //... // 1. SQLConnection is a type that implements IDisposable // 2. So you can use MyConnection in a using statement // 3. When using block finishes, it calls Dispose method of // SqlConnection class // 4. In this case, it will probably close the connection to // the database and dispose MyConnection object } 

您可以创build自己的实现IDisposable的对象:

 public class MyOwnObjectThatImplementsIDisposable : IDisposable { //... some code public void Dispose() { // Put here the code you want to be executed when the // using statement finish. } } 

所以你可以在using语句中使用MyOwnObjectThanImplementsIDisposabletypes的对象:

  using(MyOwnObjectThatImplementsIDisposable MyObject = new MyOwnObjectThatImplementsIDisposable) { // When the statement finishes, it calls the // code you´ve writed in Dispose method // of MyOwnObjectThatImplementsIDisposable class } 

希望这可以帮助

在这种情况下, using语句对于实现IDisposable的types非常有用。 当代码块退出using语句的范围时, Dispose()被隐式调用。 使用后立即处理对象时,这是一个很好的习惯。

你应该小心使用using块的一个特定实例是WCF服务客户端

正如在这篇MSDN文章中指出的那样,在一个using块中包装一个WCF客户端(它实现了IDisposable )可以掩盖导致客户端处于故障状态的任何错误(如超时或通信问题)。 长话短说,当调用Dispose()时,客户端的Close()方法会触发,但会抛出错误,因为它处于错误状态。 原来的exception然后被第二个exception所掩盖。 不好。

这里有各种解决方法,包括MSDN文章本身。 其他可以在IServiceOriented和blog.davidbarret.netfind。

我更喜欢最后的方法,我自己。

如果你想要一个总结规则。 任何时候使用IDisposable的对象在哪里你都没有catch,使用using。 本质上,使用这种模式是:

 try { //instantiate and use object } finally { //dispose object } 

如果你不需要捕捉,使用可以节省你打字,这是一件好事。

也许值得一提的是,添加“使用”lo C#languge的基本原因如下:一些资源可能稀缺到无法等待GC调用IDisposable。 例如,DB连接。 如果你使用try / catch / finally,你最终不会得到一个悬而未决的连接,但是连接将被挂起,直到GC没有启动,这可能需要一段时间(如果你没有明确地closures它)。 如果您使用“使用”(原谅双关语),即使您忘记closures它,即使在使用块内发生了一些exception,也会立即释放连接。
另一个原因,正如前面提到的,程序员并不总是最终使用清理。 如果最终不使用exception,最终会泄露资源

一种情况是当你想在代码块的开始处做一些事情,然后无条件地在块的末尾撤销它(即使有一个投掷)。

您构build的一次性类的ctor(并在使用中调用)将执行该操作,然后Dispose方法将撤消该操作。 这通常是我使用它的方式。

主要规则是:*当对象实现IDisposable接口时使用USING语句。

这个接口提供了Dispose方法,它应该释放对象的资源。 如果这个方法没有被调用,那么这个对象会一直留在内存中,因为CLR想要执行垃圾收集。 如果程序员使用USING语句,那么最后的对象将被丢弃,并且所有的资源都是免费的。

所有不再使用的资源尽快免费是非常重要的。

有关更多信息,请访问此链接: microsoft

其他人已经提到“IDisposable”了。

但使用“使用”语句时的一个注意事项是,在“使用”内抛出的任何exception都不会被捕获,即使认为“SomeType”将被处理。

所以在下面的代码片段中,

 using (SomeType t = new SomeType()){ throw new Exception("thrown within using"); } 

throw new Exception("thrown within using"); 不应该被忽视。

如果某些东西实现了IDispose ,并且如果你想要处理的东西持有NON-MANAGED资源,比如数据库连接和文件句柄,那么我还会添加using()语句。

如果这是一个正常的对象,说一个List<T> ,其中T就像一个Customer对象,它包含名称和地址,那么你不需要。 垃圾收集器很聪明,可以为你pipe理这个。 但垃圾收集器不会将连接返回到连接池或closures文件句柄。