使用Disposable对象的最佳方法是什么,假设Constructor和Process方法可能会抛出异常?我通常更喜欢以下实现之一。
使用块
尝试捕获周围环境try
{
using (Disposable dispObj = new Disposable())
{
dispObj.Process();
}
}
catch (Exception ex)
{
// Do something
}
try-catch-finally阻止。
Disposable dispObj2 = null;
try
{
dispObj2 = new Disposable();
dispObj2.Process();
}
catch (Exception ex)
{
// Do something
}
finally
{
if (dispObj2 != null)
{
dispObj2.Dispose();
}
}
更新
再次:"假设Constuctor和Process方法可能抛出异常" 。我真的不明白为什么没有人关心他们答案中的异常。
答案 0 :(得分:10)
using
很好。它有一个内置的try-finally块。如果发生异常,则自动调用dispose方法。
这很好
using (Disposable dispObj = new Disposable())
{
dispObj.Process();
}
答案 1 :(得分:3)
这样做:
using (Disposable dispObj = new Disposable())
{
dispObj.Process();
}
当一次性对象超出using
子句的范围时,它们总是被处理掉,即使它是异常的。
不要使用空的catch {}
,完全没有意义。
答案 2 :(得分:3)
using语句在后台使用try - finally,仅适用于实现IDisposable的对象。你不必使用try catch。请看以下示例(来自MSDN - using statement)。
using (Font font1 = new Font("Arial", 10.0f))
{
byte charset = font1.GdiCharSet;
}
以上代码与:
相同Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
((IDisposable)font1).Dispose();
}
答案 3 :(得分:2)
using (Disposable dispObj = new Disposable())
{
dispObj.Process();
}
}
答案 4 :(得分:1)
实现IDisposable接口的类通常使用.NET框架垃圾收集器无法清除的资源。 调用IDisposable.Dispose()方法可以执行将宝贵资源显式释放回世界的代码。 实现IDisposable接口的类的一个主要示例是SqlConnection类。 SqlConnection类使用Microsoft SQL Server数据库连接。由于SQL Server支持有限数量的连接,因此尽快释放连接非常重要。 通常,您不直接调用Dispose()方法。通常,您可以像在代码中提到的那样利用代码中的Using语句
答案 5 :(得分:0)
如果可能,您应该使用使用块。它将保证在您的对象上调用Dispose。手动执行此操作容易出错。
答案 6 :(得分:0)
using (IDisposable disp = new IDisposable())
{
//some logic here
}
此代码将翻译成以下内容:
IDisposable disp = new IDisposable();
try
{
//some logic here
}
finally
{
if (disp != null)
((IDisposable)disp).Dispose();
}
块“finally”中的代码始终执行,因此它为您提供了抛出异常的可能性,使用块返回,而不会怀疑Dispose不会被调用。
但是你应该小心使用和对象初始化器。
using (var fs = new FileStream(@"C:\blabla", FileMode.Open) { Position = pos })
{
//some logic here
}
从here属性可以看出,Position可以抛出异常。问题是该对象将被创建并且这将在 out of try block 中完成,因此可能存在内存泄漏。正确的方法
using (var fs = new FileStream(@"C:\blabla", FileMode.Open))
{
fs.Position = pos;
//some logic here
}
答案 7 :(得分:0)
您提出的方法#1可能是实现您想要的最简洁的方法。
周围的try
... catch
块应该捕获任何抛出的异常,包括构造函数抛出的异常。如果在使用一次性对象时(在using
块内)发生异常,则该对象也将在catch
接管之前处置。
方法#2从方法#1获取不同的执行路径。请注意,根据C# Reference,方法#1按字面编译,就好像编写了以下内容一样:
try
{
{
Disposable dispObj = new Disposable();
try
{
dispObj.Process();
}
finally
{
if (dispObj != null)
((IDisposable)dispObj).Dispose();
}
}
}
catch (Exception ex)
{
// Do something
}
因此,两种方法之间的范围是不同的。在可能的情况下,我更喜欢方法#1,因为范围问题,也因为它更容易阅读。