在该IDisposable.Dispose
方法中有一种方法可以确定是否抛出异常?
using (MyWrapper wrapper = new MyWrapper()) { throw new Exception("Bad error."); }
如果在using
语句中抛出异常,我想在处理IDisposable
对象时知道它.
您可以IDisposable
使用方法扩展Complete
并使用以下模式:
using (MyWrapper wrapper = new MyWrapper()) { throw new Exception("Bad error."); wrapper.Complete(); }
如果在using
语句中抛出异常,则Complete
之前不会调用该语句Dispose
.
如果您想知道抛出了什么确切的异常,那么订阅AppDomain.CurrentDomain.FirstChanceException
事件并将最后抛出的异常存储在ThreadLocal
变量中.
这种模式在TransactionScope
课堂上实施.
不,在.Net框架中没有办法做到这一点,你无法弄清楚finally子句中正在抛出的当前异常.
在我的博客上看到这篇文章,为了与Ruby中的类似模式进行比较,它突出了我认为存在于IDisposable模式中的差距.
Ayende有一个技巧,可以让你检测到发生的异常,但是,它不会告诉你它是哪个异常.
这是不可能捕获的异常Dispose()
的方法.
但是,可以检查Marshal.GetExceptionCode()
Dispose以检测是否确实发生了异常,但我不会依赖它.
如果您不需要类并且只想捕获Exception,则可以创建一个接受在try/catch块中执行的lambda的函数,如下所示:
HandleException(() => { throw new Exception("Bad error."); }); public static void HandleException(Action code) { try { if (code != null) code.Invoke(); } catch { Console.WriteLine("Error handling"); throw; } }
例如,您可以使用自动执行事务的Commit()或Rollback()并执行某些日志记录的方法.通过这种方式,您并不总是需要try/catch块.
public static int? GetFerrariId() { using (var connection = new SqlConnection("...")) { connection.Open(); using (var transaction = connection.BeginTransaction()) { return HandleTranaction(transaction, () => { using (var command = connection.CreateCommand()) { command.Transaction = transaction; command.CommandText = "SELECT CarID FROM Cars WHERE Brand = 'Ferrari'"; return (int?)command.ExecuteScalar(); } }); } } } public static T HandleTranaction(IDbTransaction transaction, Func code) { try { var result = code != null ? code.Invoke() : default(T); transaction.Commit(); return result; } catch { transaction.Rollback(); throw; } }