我的理解是,一旦代码退出块,.NET中的using
statement就会调用IDisposable
对象的Dispose()
方法。
using
语句是否还有其他功能?如果没有,似乎以下两个代码示例完全相同:
Using Con as New Connection()
Con.Open()
'do whatever '
End Using
Dim Con as New Connection()
Con.Open()
'do whatever '
Con.Dispose()
我会给那些确认我是正确的人或者指出我错了并给出解释原因的人给出最好的答案。请记住,我知道某些类可以在Dispose()
方法中执行不同的操作。这个问题是关于using
语句是否达到与调用对象的Dispose()
方法完全相同的结果。
答案 0 :(得分:63)
using
基本上相当于:
try
{
// code
}
finally
{
obj.Dispose();
}
因此即使在块内的代码中抛出未处理的异常,它也有调用Dispose()
的好处。
答案 1 :(得分:18)
正如 Brian Warshaw 在here中所述,它只是try
和finally
块的实现,以确保处置对象。除了他的答案之外,using
阻止还确保即使您使用范围 返回内部也会处置该对象。
我曾经对此感到好奇并使用以下方法对其进行了测试:
自定义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();
}
测试用例实施
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(); }
}
}
输出是:
答案 2 :(得分:9)
//preceeding code
using (con = new Connection()) {
con.Open()
//do whatever
}
//following code
等同于以下(注意con的范围有限):
//preceeding code
{
var con = new Connection();
try {
con.Open()
//do whatever
} finally {
if (con != null) con.Dispose();
}
}
//following code
这里描述:http://msdn.microsoft.com/en-us/library/yh598w02.aspx
using语句确保即使调用Dispose也会调用 在对象上调用方法时发生异常。 你可以 通过将对象放在try块中来实现相同的结果 然后在finally块中调用Dispose;其实这是怎么回事 using语句由编译器翻译。
答案 3 :(得分:6)
using
语句比try...finally{Dispose()}
构造更清晰,更简洁,并且应该在几乎所有不希望允许块退出而没有Dispose
的情况下使用调用。 “手动”处理会更好的唯一常见情况是:
请注意,从工厂方法返回IDisposable
时,应使用以下内容:
bool ok = false; DisposableClass myThing; try { myThing = new DisposableClass(); ... ok = true; return myThing; } finally { if (!ok) { if (myThing != null) myThing.Dispose(); } }
确保myThing
如果没有返回Dispose
将获得using
。我希望有一种方法可以使用{{1}}以及一些“取消Dispose”方法,但不存在这样的事情。
答案 4 :(得分:5)
两者之间的区别在于,如果在
中抛出异常Con.Open()
'do whatever
Con.Dispose
将不会被调用。
我没有使用VB语法,但在C#中,等效代码将是
try
{
con = new Connection();
// Do whatever
}
finally
{
if (con != null) con.Dispose();
}
答案 5 :(得分:3)
using
语句保证在抛出异常的情况下处理对象。这相当于在finally
块中调用dispose。
答案 6 :(得分:3)
使用在finally /块中调用Dispose的try / finally包装封闭的块。这确保即使发生异常也会调用Dispose。
出于安全原因,您几乎应该在所有情况下都使用
答案 7 :(得分:2)
using块确保在抛出异常时调用Dispose()
。
你的第二个样本没有这样做。
如果Con.Open()
引发了异常,在第一种情况下,您可以保证调用Con.Dispose()
。在第二种情况下,异常传播,并且不会调用Con.Dispose()
。
答案 8 :(得分:1)
如果内存服务,则使用是保证对象被丢弃,无论它所围绕的代码块是如何退出的。它通过在try ... finally块中包围块来执行此操作,并检查使用的变量是否为null,然后在它不为null时处理它。如果抛出异常,则允许冒泡堆栈。除此之外,它所做的只是保证处理非零的一次性物品。
try
{
var myDisposable = new DisposableObject();
myDisposable.DoSomething();
}
finally
{
if (myDisposable != null)
((IDisposable)myDisposable).Dispose();
}