C# 使用语句与 IDisposable.Dispose()
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10984336/
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
Using statement vs. IDisposable.Dispose()
提问by oscilatingcretin
It has been my understanding that the usingstatementin .NET calls an IDisposableobject's Dispose()method once the code exits the block.
我的理解是,一旦代码退出块,.NET中的using语句就会调用IDisposable对象的Dispose()方法。
Does the usingstatement do anything else? If not, it would seem that the following two code samples achieve the exact same thing:
请问using声明要做什么吗?如果没有,以下两个代码示例似乎实现了完全相同的事情:
Using Con as New Connection()
Con.Open()
'do whatever '
End Using
Dim Con as New Connection()
Con.Open()
'do whatever '
Con.Dispose()
I will give the best answer to whoever confirms that I am correct or points out that I am wrong and explains why. Keep in mind that I am aware that certain classes can do different thingsin their Dispose()methods. This question is about whether or not the usingstatement achieves the exact same result as calling an object's Dispose()method.
我会为确认我正确或指出我错并解释原因的人给出最佳答案。请记住,我知道某些类可以在它们的Dispose()方法中做不同的事情。这个问题是关于该using语句是否获得与调用对象Dispose()方法完全相同的结果。
采纳答案by Brian Warshaw
usingis basically the equivalent of:
using基本上相当于:
try
{
// code
}
finally
{
obj.Dispose();
}
So it also has the benefit of calling Dispose()even if an unhandled exception is thrown in the code within the block.
因此,Dispose()即使在块内的代码中抛出未处理的异常,它也具有调用的好处。
回答by jglouie
The using block makes sure that Dispose()is called if an exception is thrown.
using 块确保Dispose()在抛出异常时调用它。
Your second sample does not do that.
你的第二个样本没有这样做。
If Con.Open()threw an exception, in the first case you are guaranteed that Con.Dispose()is called. In the second case, the exception propagates up and Con.Dispose()will not be called.
如果Con.Open()抛出异常,在第一种情况下,您可以保证Con.Dispose()被调用。在第二种情况下,异常Con.Dispose()会向上传播并且不会被调用。
回答by Eric J.
The difference between the two is that, if an Exception is thrown in
两者的区别在于,如果抛出异常
Con.Open()
'do whatever
Con.Disposewill not be called.
Con.Dispose不会被调用。
I'm not up on VB syntax, but in C#, the equivalent code would be
我不了解 VB 语法,但在 C# 中,等效代码是
try
{
con = new Connection();
// Do whatever
}
finally
{
if (con != null) con.Dispose();
}
回答by jrummell
The usingstatement guarantees that the object is disposed in the event an exception is thrown. It's the equivalent of calling dispose in a finallyblock.
该using语句保证在抛出异常时处理对象。这相当于在finally块中调用 dispose 。
回答by Panagiotis Kanavos
Using wraps the enclosed block in a try/finally that calls Dispose in the finally block. This ensures that Dispose will be called even if an exception occurs.
Using 将封闭块包装在 try/finally 中,在 finally 块中调用 Dispose。这确保即使发生异常也会调用 Dispose。
You should use usingin almost all cases, for safety reasons
出于安全原因,您应该在几乎所有情况下使用using
回答by Mike Hofer
If memory serves, using is a guarantee that an object is disposed of regardless of how the block of code it surrounds exits it. It does this by surrounding the block in a try...finally block, and checking the usedvariable for nullness, and then disposing of it if it is not null. If an exception was thrown, it's allowed to bubble up the stack. Aside from that, all it does is guarantee disposal of non-null disposable objects.
如果内存有用, using 是一个保证,无论对象周围的代码块如何退出它,对象都会被处理。它通过在 try...finally 块中包围块来实现这一点,并检查使用的变量是否为空,如果它不为空则将其处理掉。如果抛出异常,则允许在堆栈中冒泡。除此之外,它所做的只是保证处理非空的一次性对象。
try
{
var myDisposable = new DisposableObject();
myDisposable.DoSomething();
}
finally
{
if (myDisposable != null)
((IDisposable)myDisposable).Dispose();
}
回答by hatchet - done with SOverflow
//preceeding code
using (con = new Connection()) {
con.Open()
//do whatever
}
//following code
is equivalent to the following (note the limited scope for con):
等效于以下内容(注意 con 的有限范围):
//preceeding code
{
var con = new Connection();
try {
con.Open()
//do whatever
} finally {
if (con != null) con.Dispose();
}
}
//following code
This is described here: http://msdn.microsoft.com/en-us/library/yh598w02.aspx
这在这里描述:http: //msdn.microsoft.com/en-us/library/yh598w02.aspx
The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.
using 语句确保 Dispose 被调用,即使在您调用对象的方法时发生异常。您可以通过将对象放在 try 块中,然后在 finally 块中调用 Dispose 来获得相同的结果;事实上,这就是编译器如何翻译 using 语句。
回答by supercat
A usingstatement is clearer and more concise than a try...finally{Dispose()}construct, and should be used in nearly all cases where one does not want to allow a block to exit without Disposebeing called. The only common situations where "manual" disposal would be better would be when:
一个using说法是不是更清晰和更简洁的try...finally{Dispose()}构造,并应在几乎所有情况下,人们不希望允许退出块没有被使用Dispose被调用。“手动”处理会更好的唯一常见情况是:
- A method calls a factory method which returns something that may or may not implement `IDisposable`, but which should be `Dispose`d if it does (a scenario which occurs with non-generic `IEnumerable.GetEnumerator()`). Well-designed factory interfaces should either return a type that implements `IDisposable` (perhaps with a do-nothing implementation, as is typically the case of `IEnumerator`) or else specify callers are not expected to `Dispose` the returned object. Unfortunately, some interfaces like non-generic `IEnumerable` satisfy neither criterion. Note that one cannot very well use `using` in such cases, since it only works with storage locations whose declared type implements `IDisposable`.
- The `IDisposable` object is expected to live even after the block is exited (as is often the case when setting an `IDisposable` field, or returning an `IDisposable` from a factory method).
- 一个方法调用一个工厂方法,它返回的东西可能会或可能不会实现`IDisposable`,但是如果它实现了,它应该是`Dispose`d(发生在非通用`IEnumerable.GetEnumerator()`的情况)。设计良好的工厂接口应该要么返回一个实现`IDisposable` 的类型(可能是一个什么都不做的实现,就像`IEnumerator` 的典型情况),或者指定调用者不应该`Dispose` 返回的对象。不幸的是,像非通用的“IEnumerable”这样的接口不满足这两个标准。请注意,在这种情况下不能很好地使用 `using`,因为它只适用于声明类型实现 `IDisposable` 的存储位置。
- 即使在块退出后,“IDisposable”对象也有望继续存在(通常在设置“IDisposable”字段或从工厂方法返回“IDisposable”时就是这种情况)。
Note that when returning an IDisposablefrom a factory method, one should use something like the following:
请注意,IDisposable从工厂方法返回 an 时,应使用以下内容:
bool ok = false;
DisposableClass myThing;
try
{
myThing = new DisposableClass();
...
ok = true;
return myThing;
}
finally
{
if (!ok)
{
if (myThing != null)
myThing.Dispose();
}
}
to ensure that myThingwill get Disposed if it doesn't get returned. I wish there was a way to employ usingalong with some "cancel Dispose" method, but no such thing exists.
确保如果没有返回,myThing它将得到Disposed 。我希望有一种方法可以using与一些“取消处理”方法一起使用,但不存在这样的东西。
回答by Saro Ta?ciyan
As Brian Warshawstated in hereit's simply an implementation of tryand finallyblock to make sure object is disposed. Adding to his answer, usingblock also makes sure that the object is disposed even if you returninside using scope.
正如Brian Warshaw在这里所说的,它只是一个try和finally块的实现,以确保对象被释放。添加到他的回答中,using即使您使用scope返回内部,block 也可以确保对象被释放。
I was once curious about this myself and tested it out using the following approach:
我曾经对此感到好奇,并使用以下方法对其进行了测试:
Custom IDisposable test class and Main
自定义 IDisposable 测试类和 Main
private class DisposableTest : IDisposable
{
public string Name { get; set; }
public void Dispose() { Console.WriteLine("{0}.Dispose() is called !", Name); }
}
public static void Main(string[] args)
{
try
{
UsingReturnTest();
UsingExceptionTest();
}
catch { }
try
{
DisposeReturnTest();
DisposeExceptionTest();
}
catch { }
DisposeExtraTest();
Console.ReadLine();
}
Test cases implementation
测试用例实现
private static string UsingReturnTest()
{
using (DisposableTest usingReturn = new DisposableTest() { Name = "UsingReturn" })
{
return usingReturn.Name;
}
}
private static void UsingExceptionTest()
{
using (DisposableTest usingException = new DisposableTest() { Name = "UsingException" })
{
int x = int.Parse("NaN");
}
}
private static string DisposeReturnTest()
{
DisposableTest disposeReturn = new DisposableTest() { Name = "DisposeReturn" };
return disposeReturn.Name;
disposeReturn.Dispose(); // # IDE Warning; Unreachable code detected
}
private static void DisposeExceptionTest()
{
DisposableTest disposeException = new DisposableTest() { Name = "DisposeException" };
int x = int.Parse("NaN");
disposeException.Dispose();
}
private static void DisposeExtraTest()
{
DisposableTest disposeExtra = null;
try
{
disposeExtra = new DisposableTest() { Name = "DisposeExtra" };
return;
}
catch { }
finally
{
if (disposeExtra != null) { disposeExtra.Dispose(); }
}
}
And the outputis:
而输出是:
- UsingReturn.Dispose() is called !
- UsingException.Dispose() is called !
- DisposeExtra.Dispose() is called !
- 调用 UsingReturn.Dispose() !
- 调用 UsingException.Dispose() !
- DisposeExtra.Dispose() 被调用!

