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

是否有一些特殊的情况,我应该(或不应该)使用“ using”块:

using(SomeType t = new SomeType()){
...
}
87843 次浏览

SomeType类实现 IDisposable时。

每当类型实现 IDisposable时都使用 using,除非您打算将它包装在 ABC2/catch块中,那么您也可以(取决于您喜欢的外观)使用 finally块。

SomType 实现 IDisposable 时。

对于开发人员来说,这是一个线索,表明 SomType 使用了需要清理的非托管资源。

在此上下文中,using语句对于实现 IDisposable 的类型很方便。当代码块退出 using语句的作用域时,将隐式调用 Dispose()。在使用希望在使用后立即处理的对象时,这是一个好习惯。

一种情况是,您希望在代码块开始时执行某些操作,然后在代码块结束时无条件地撤消该操作(即使有抛出操作)。

构建的一次性类的 ctor (并在 using 中调用)将执行该操作,然后 Dispose 方法将撤消该操作。我一般都是这么用的。

首要原则是: * 对象实现 IDisposable 接口时使用 USING 语句。

此接口提供 Dispose 方法,该方法应释放对象的资源。如果不调用此方法,那么对象将一直保留在内存中,因为 CLR 希望执行垃圾收集。如果程序员使用 USING 语句,那么最终对象将被释放,所有资源将被释放。

所有不再使用的资源必须尽快免费,这一点非常重要。

有关它的更多信息,请访问这个链接: 微软

其他人已经提到了“一次性手机”。

但使用“ using”语句时需要注意的一点是, 在“ using”中抛出的任何异常都不会被捕获 即使“有些类型”会不顾一切地被丢弃。

因此,在下面的代码片段中,

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

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

例如:

        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


}

您可以创建自己的实现 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 语句中使用 MyOwnObjectThanIntegrmentsIDisposable 类型的对象:

        using(MyOwnObjectThatImplementsIDisposable MyObject = new MyOwnObjectThatImplementsIDisposable)
{


// When the statement finishes, it calls the
// code you´ve writed in Dispose method
// of MyOwnObjectThatImplementsIDisposable class
}

希望这个能帮上忙

有些对象需要在完成处理后采取某些操作。通常这是因为对象使用了某种需要处理的资源。例如,如果您有一个 File 类的 File 对象,并且该对象从文件系统打开一个文件,则需要再次关闭文件系统中的文件。

如果您只是离开 file 对象,而忘记调用 file。Close ()直到垃圾收集器(GC)运行并发现没有任何东西仍在使用 file 对象时才会清理。垃圾收集器何时运行应由通用语言运行库(CLR)决定。如果在处理完文件之后 GC 很长一段时间都没有运行,那么文件可能会打开很长一段时间。如果有许多文件对象,或者有些东西想要打开一个文件,但是不能打开,因为您留下的文件对象仍然挂起,那么这可能会造成很大的问题。

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

为了解决这个问题,C # 引入了‘ using’关键字。您可以在新建对象的周围放置一个“ using”关键字,这样可以确保 Dispose 将被调用。它保证 Dispose 在任何情况下都会被调用... ... 即使 using 语句体中引发了异常。

因此,当您希望确保分配资源的对象将被清除时,应该使用“ using”。


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


需要对它们进行调用的常见对象有: 文件、数据库连接、钢笔和画笔等图形对象。


有时,当您希望两个操作同时发生时,也可以使用它。例如,如果您希望在输入代码块并退出代码块时编写日志语句,那么您可以编写一个日志类,您可以像下面这样使用:

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

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

当你的 应该有一个 using语句时,我看到许多其他的答案。我想谈谈什么时候 没有应该有一个 using语句:

如果需要在当前函数的作用域之外使用对象,请不要使用 using块。好的例子是返回数据库连接的工厂方法或需要返回数据读取器的方法。在这两种情况下,如果您使用 using语句创建对象,它将在方法返回之前被释放,因此不能在方法之外使用。

现在,您仍然希望是 当然,以便释放那些对象,因此您仍然可能希望在某个地方使用 using语句。只是不要将它包含在实际创建对象的方法中。相反,您可以将函数调用本身包装在 using语句中。

也许值得一提的是,添加“使用”lo C # 语言的根本原因如下: 一些资源可能非常稀缺,因此等待 GC 调用 IDisposable 是没有意义的。例如,DB 连接。如果您使用 try/catch/finally,您将不会得到一个悬空连接,但是连接将被挂起,直到 GC 不再生效,这可能需要一段时间(如果您没有显式地关闭它)。如果您使用“ using”(请原谅双关语) ,即使您忘记关闭连接,即使在 using 块中发生了一些异常,您也会立即释放连接。
另一个原因,正如前面提到的,是程序员并不总是使用 finally 来清理。如果在异常情况下没有使用 finally,那么最终将导致资源泄漏..。

我还要补充的是,如果某些东西实现了 IDispose,并且如果您希望处置的某些东西持有非 MANAGED 资源(如数据库连接和文件句柄) ,则使用 using()语句。

如果它是一个普通的对象,比如 List<T>,其中 T 类似于保存名称和地址的 Customer对象,那么就不需要这样做。垃圾收集器足够聪明,可以为您管理这些。但是垃圾收集器不会返回到连接池的连接或关闭文件句柄。

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

正如在 这篇 MSDN 的文章中指出的,在 using块中包装 WCF 客户机(它实现了 IDisposable)可以掩盖任何导致客户机处于错误状态(比如超时或通信问题)的错误。长话短说,当调用 Dispose()时,客户机的 Close()方法触发,但是抛出并出错,因为它处于错误状态。然后第二个异常将掩盖原始异常。情况不妙。

有各种各样的变通方法,包括 MSDN 文章本身中的一种。其他的可以在 面向服务Blog.davidbarret.net找到。

我个人比较喜欢最后一种方法。

如果需要汇总规则。任何时候,当使用 IDisposable 的对象没有 catch 时,使用。本质上,使用的是这种模式:

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

如果您不需要捕获,使用可以节省您的输入,这是一件好事。