我什么时候应该在 C# 中使用“using”块?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/567138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When should I use "using" blocks in C#?
提问by Mark Carpenter
Are there particular instances where I should (or shouldn't?) be using "using" blocks:
是否存在我应该(或不应该?)使用“使用”块的特定情况:
using(SomeType t = new SomeType()){
...
}
采纳答案by Otávio Décio
When the SomeType
class implements IDisposable
.
当SomeType
类实现IDisposable
.
回答by bdukes
Use using
whenever the type implements IDisposable
, unless you're going to wrap it in a try
/catch
block anyway, then you might as well (depending on what look you prefer) use a finally
block.
using
每当类型实现时使用IDisposable
,除非您无论如何都要将它包装在try
/catch
块中,那么您也可以(取决于您喜欢的外观)使用finally
块。
回答by mbeckish
When SomeType implements IDisposable.
当 SomeType 实现 IDisposable 时。
That is a clue to you the developer that SomeType uses unmanaged resources that need to be cleaned up.
这对您的开发人员来说是一个线索,即 SomeType 使用需要清理的非托管资源。
回答by Dave Swersky
In this context the using
statement is handy for types that implement IDisposable. When the code block exits the scope of the using
statement, Dispose()
is called implicitly. It's a good habit when working with objects you want to dispose immediately after use.
在这种情况下,该using
语句对于实现 IDisposable 的类型很方便。当代码块退出using
语句的作用域时,Dispose()
被隐式调用。处理使用后要立即处理的对象时,这是一个好习惯。
回答by Allen Rice
One situation is when you want to do something at the beginning of a code block, and then undo it at the end of the block, unconditionally (even if there is a throw).
一种情况是当您想在代码块的开头做某事,然后在块的末尾无条件地撤消它(即使有抛出)。
The ctor for the disposable class that you build (and call within the using) would perform the action, and then the Dispose method would undo that action. This is typically how I use it.
您构建(并在 using 中调用)的一次性类的 ctor 将执行该操作,然后 Dispose 方法将撤消该操作。这通常是我使用它的方式。
回答by rpf
The primary rule is: * Use USING statement when objects implements IDisposable interface.
主要规则是: * 当对象实现 IDisposable 接口时使用 USING 语句。
This interface provides the Dispose method, which should release the object's resources. If this method is not invoked then the object will stay in memory as long, as CLR wants to perform garbage collection. If the programmer use the USING statement then on the end the object will be disposed, and all resources will be free.
该接口提供了 Dispose 方法,该方法应该释放对象的资源。如果未调用此方法,则该对象将在内存中停留很长时间,因为 CLR 想要执行垃圾回收。如果程序员使用 USING 语句,那么最终对象将被释放,所有资源都将被释放。
It is very important that all resources that are no longer in use be free as soon as possible.
所有不再使用的资源尽快免费是非常重要的。
For more information about it just visit this link: microsoft
有关它的更多信息,请访问此链接:microsoft
回答by dance2die
Other people has mentioned about "IDisposable" already.
其他人已经提到了“IDisposable”。
But one of the caveats when using "using" statement is that, any exceptions thrown within "using" will not be caught even thought "SomeType" will be disposed regardless.
但是使用“using”语句时的警告之一是,即使认为“SomeType”都会被处理,也不会捕获“using”中抛出的任何异常。
So in the following snippet,
所以在下面的片段中,
using (SomeType t = new SomeType()){
throw new Exception("thrown within using");
}
throw new Exception("thrown within using");
should not be disregarded.
throw new Exception("thrown within using");
不应该被忽视。
回答by Javier
Example:
例子:
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
}
You can create your own objects that implements IDisposable:
您可以创建自己的实现 IDisposable 的对象:
public class MyOwnObjectThatImplementsIDisposable : IDisposable
{
//... some code
public void Dispose()
{
// Put here the code you want to be executed when the
// using statement finish.
}
}
So you could use an object of MyOwnObjectThanImplementsIDisposable type in a using statement:
因此,您可以在 using 语句中使用 MyOwnObjectThanImplementsIDisposable 类型的对象:
using(MyOwnObjectThatImplementsIDisposable MyObject = new MyOwnObjectThatImplementsIDisposable)
{
// When the statement finishes, it calls the
// code you′ve writed in Dispose method
// of MyOwnObjectThatImplementsIDisposable class
}
Hope this helps
希望这可以帮助
回答by Scott Langham
Some objects need some action to be taken when you have finished with them. Usually this is because the object uses some kind of resource that needs to be disposed of. For example, if you have a file object of class File, and this object opens a file from the file system, the file in the file system will need to be closed again.
有些对象需要在您完成它们后采取一些操作。通常这是因为对象使用了某种需要处理的资源。例如,如果您有一个 File 类的文件对象,并且该对象从文件系统打开一个文件,则文件系统中的文件将需要再次关闭。
If you just left the file object, and forgot to call file.Close() it wouldn't be cleaned up until the Garbage Collector (GC) ran and worked out nothing was still using the file object. When the Garbage Collector runs should be left to the Common Language Runtime (CLR) to decide. If the GC doesn't run for quite a while after you have finished with the file, the file could remain open potentially for a long time. This can pose a big problem if there are many file objects, or if something wants to open a file, but can't because the file object you left is still hanging around.
如果您刚刚离开文件对象,而忘记调用 file.Close(),则在垃圾收集器 (GC) 运行并确定没有任何内容仍在使用文件对象之前,它不会被清除。垃圾收集器何时运行应该由公共语言运行时 (CLR) 来决定。如果 GC 在您处理完文件后很长时间没有运行,则该文件可能会长时间保持打开状态。如果有很多文件对象,或者如果有东西想打开一个文件,但不能打开,因为你留下的文件对象仍然存在,这可能会带来一个大问题。
To solve this problem, C# has the IDisposable interface. This has one method called Dispose. Classes that require some cleanup implement this Dispose method. This gives you a standard way for cleaning up any objects that use resources. There are a lot of classes that need to have Dispose called. The problem with this is that code gets covered with calls to Dispose, and they are tricky to follow because the place where you new'ed the object and call Dispose to clean it up are different. So, you had to look around the code a lot and be very careful to check there were calls to Dispose in the right place.
为了解决这个问题,C# 提供了 IDisposable 接口。这有一种称为 Dispose 的方法。需要一些清理的类实现此 Dispose 方法。这为您提供了一种清理使用资源的任何对象的标准方法。有很多类需要调用 Dispose。这样做的问题是代码会被对 Dispose 的调用所覆盖,而且它们很难跟踪,因为您新建对象和调用 Dispose 来清理它的地方是不同的。因此,您必须仔细查看代码,并非常小心地检查是否在正确的位置调用了 Dispose。
To solve this problem C# introduced the 'using' keyword. You can put a 'using' keyword around where you new an object, and this ensures Dispose will be called on it for you. It guarantees that Dispose will be called whatever happens... even if there is an exception thrown within the body of the using statement.
为了解决这个问题,C# 引入了 'using' 关键字。你可以在你新建一个对象的地方放一个“using”关键字,这样可以确保为你调用 Dispose。它保证无论发生什么都会调用 Dispose ......即使在 using 语句的主体中抛出异常。
So, you should use 'using' when you want to be sure an object that allocates resources will be cleaned up.
因此,当您想确保分配资源的对象将被清理时,您应该使用“使用”。
using can only be used for objects that are declared on the stack, i.e. in a function. It doesn't work for objects that are declared as members of a class. For them, you have to call Dispose yourself. You may have to implement Dispose in your class so that in can call Dispose on any member objects it has that require it.
using 只能用于在堆栈上声明的对象,即在函数中。它不适用于声明为类成员的对象。对于他们,您必须自己调用 Dispose。您可能必须在您的类中实现 Dispose,以便可以在需要它的任何成员对象上调用 Dispose。
Common objects that need using called on them are: Files, Database connections, Graphics objects such as Pen and Brush.
需要调用它们的常见对象有:文件、数据库连接、图形对象,例如笔和画笔。
Sometimes it is also used when you want two operations to happen together. For example if you want to write a log statement when a block of code is entered and when it exits you could write a log class that you could use like this:
有时,当您希望两个操作一起发生时,也会使用它。例如,如果您想在输入代码块和退出代码块时编写日志语句,您可以编写一个日志类,您可以像这样使用:
using( Log log = new Log("Doing stuff") )
{
// Stuff
}
The constructor for the log class could be made to write out the message, and the Dispose method could also write it out. Implement the finalizer (~Log) to assert if the Dispose method doesn't get called to ensure the 'using' is remembered around the 'new Log'.
日志类的构造函数可以用来写出消息,Dispose 方法也可以写出来。实现终结器 (~Log) 以断言是否未调用 Dispose 方法以确保在“新日志”周围记住“使用”。
回答by Joel Coehoorn
I see plenty of other answers indicated when you shouldhave a using
statement. I want to address when specifically should nothave a using
statement:
我看到很多其他的答案时表示你应该有一个using
说法。我想地址时,特别应该不会有一个using
说法:
If you need to use your object outside of the scope of the current function, don't have a using
block. Good example are a factory method that returns a database connection or a method that needs to return a datareader. In either of those cases if you create your object with a using
statement it would be disposed before the method returned, and therefore not usable outside the method.
如果您需要在当前函数的范围之外使用您的对象,请不要使用using
块。很好的例子是返回数据库连接的工厂方法或需要返回数据读取器的方法。在这两种情况下,如果您使用using
语句创建对象,它将在方法返回之前被释放,因此不能在方法之外使用。
Now, you still want to be surethat those objects are disposed, so you still might want a using
statement somewhere. Just don't include it in the method where the object is actually created. Instead, you can wrap the function call itself in a using
statement.
现在,您仍然希望确保这些对象已被释放,因此您仍然可能需要在using
某处声明。只是不要将它包含在实际创建对象的方法中。相反,您可以将函数调用本身包装在一个using
语句中。