C# 如何处理一次性对象引发的异常?
假设构造函数和进程方法可能引发异常,那么使用一次性对象的最佳方法是什么?我通常更喜欢以下实现之一C# 如何处理一次性对象引发的异常?,c#,idisposable,C#,Idisposable,假设构造函数和进程方法可能引发异常,那么使用一次性对象的最佳方法是什么?我通常更喜欢以下实现之一 尝试使用块捕捉周围 try { using (Disposable dispObj = new Disposable()) { dispObj.Process(); } } catch (Exception ex) { // Do something } 试着抓住最后一块 Disposable dispObj2 = null; try {
try
{
using (Disposable dispObj = new Disposable())
{
dispObj.Process();
}
}
catch (Exception ex)
{
// Do something
}
Disposable dispObj2 = null;
try
{
dispObj2 = new Disposable();
dispObj2.Process();
}
catch (Exception ex)
{
// Do something
}
finally
{
if (dispObj2 != null)
{
dispObj2.Dispose();
}
}
同样:“假设构造函数和进程方法可能引发异常”。我真的不明白为什么没有人关心他们答案中的例外情况。
使用
是好的。它有一个内置的try finally块。若发生异常,将自动调用dispose方法
这很好
using (Disposable dispObj = new Disposable())
{
dispObj.Process();
}
这样做:
using (Disposable dispObj = new Disposable())
{
dispObj.Process();
}
IDisposable disp = new IDisposable();
try
{
//some logic here
}
finally
{
if (disp != null)
((IDisposable)disp).Dispose();
}
使用子句时,当一次性对象超出的范围时,始终会对其进行处置,即使这是由异常引起的
不要使用空的catch{}
,它完全没有意义。在可能的情况下,应该使用using块。它将保证对对象调用Dispose。手动执行此操作容易出错。实现IDisposable接口的类通常使用.NET framework垃圾收集器无法清理的资源。
调用IDisposable.Dispose()方法执行显式释放宝贵资源的代码。
实现IDisposable接口的类的一个主要示例是SqlConnection类。SqlConnection类使用Microsoft SQL Server数据库连接。由于SQL Server支持有限数量的连接,因此尽快释放连接非常重要。
通常,您不会直接调用Dispose()方法。通常,您可以在代码中利用Using语句,就像您在代码中提到的那样,Using语句在后台使用try-finally,并且只与实现IDisposable的对象一起工作。你不必用try-catch和using。请看下面的示例(来自)
上述代码与以下代码相同:
Font font1 = new Font("Arial", 10.0f);
try
{
byte charset = font1.GdiCharSet;
}
finally
{
if (font1 != null)
((IDisposable)font1).Dispose();
}
此代码将被翻译成如下内容:
using (Disposable dispObj = new Disposable())
{
dispObj.Process();
}
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
}
正如您从属性中看到的,Position可以抛出异常。问题是对象将被创建,并且这将在try块外执行,所以可能会出现内存泄漏。正确的方法
using (var fs = new FileStream(@"C:\blabla", FileMode.Open))
{
fs.Position = pos;
//some logic here
}
你提出的方法#1可能是实现你想要的最简洁的方法
周围的try
…catch
块应该捕获抛出的任何异常,包括构造函数抛出的异常。如果在使用一次性对象时(在using
块内)发生异常,则该对象也将在catch
接管之前被处置
方法2采用与方法1不同的执行路径。请注意,根据,方法#1按字面意思编译,就好像编写了以下内容:
try
{
{
Disposable dispObj = new Disposable();
try
{
dispObj.Process();
}
finally
{
if (dispObj != null)
((IDisposable)dispObj).Dispose();
}
}
}
catch (Exception ex)
{
// Do something
}
因此,这两种方法的范围是不同的。如果可能的话,我更喜欢方法#1,因为范围问题,也因为它更容易阅读。为什么空的catch{}
?您的类一次性的必须实现,顺便说一句。您还应该实现IDisposable
来调用任何组合对象(无论是在成员字段还是属性中)上的Dispose
实现IDisposable
本身。如果构造函数或过程方法引发异常怎么办?那么它也会被处理。@NikhilAgrawal需要在注释中引用如果构造函数或过程方法引发异常怎么办?如果构造函数或过程方法引发异常怎么办?这就是使用
子句的全部要点。即使发生异常,它也将始终处理在其中构造的对象。它基本上就像使用try/finally,只是写得少一些。我甚至在这个回答中这样说,我知道,但我想学习的是人们如何处理一次性物品引发的异常。try-catch-finally或try-catch-ounding-using-block或其他东西。如果您有一个一次性对象,并且希望以特定的方式处理异常,我建议使用try/catch/finally。在finally-dispose中,在catch-handle异常中。当然,这有点取决于您是否能够在代码中指出异常应该发生的位置,在这种情况下,您可能希望使用使用,然后用try/catch将可能失败的部分包围起来。如果构造函数或进程方法引发异常怎么办?如果“某个逻辑”或“新文件流”方法引发异常怎么办?如果“new FileStream”抛出异常“OK”。对象未创建,所以没有要处理的内容。如果“有逻辑”抛出异常,dispose将从最后调用。好的,我知道,但异常处理如何?这个问题是:您更喜欢使用try-catch还是使用try-catch-finally或其他方法?第一种方法的一个问题是,如果using
调用的Dispose
方法抛出异常(可能是试图关闭弹出的USB驱动器上的文件)使用
块本身无法知道中是否发生异常。在Dispose
可能引发异常的情况下,最好在其中包含一个catch
,以确保引发的异常不会被覆盖。进一步阅读@supercat提出的问题:
try
{
{
Disposable dispObj = new Disposable();
try
{
dispObj.Process();
}
finally
{
if (dispObj != null)
((IDisposable)dispObj).Dispose();
}
}
}
catch (Exception ex)
{
// Do something
}