当前位置: 首页 > 编程语言 > C#

如何判断.NET异常是否被处理?分享

时间:2023-04-11 02:42:47 C#

如何判断是否正在处理.NET异常?我们正在研究C#中的一种编码模式,其中我们希望有一个带有特殊类的“using”子句,其Dispose()方法根据“using”主体是正常退出还是异常退出执行不同的操作。据我所知,CLR会跟踪当前正在处理的异常,直到它被“捕获”处理程序使用为止。但是,尚不完全清楚此信息是否以任何方式暴露给代码访问。你知道它是否是,如果是,如何访问它?例如:使用(varx=newMyObject()){x.DoSomething();x.DoMoreThings();}classMyObject:IDisposable{publicvoidDispose(){if(ExceptionIsBeingHandled)Rollback();否则提交();这看起来和System.Transactions.TransactionScope差不多,只是成功/失败不是通过调用x.Complete()来确定的,而是根据using文字是否正常退出来确定的。http://www.codewrecks.com/blog/index.php/2008/07/25/detecting-if-finally-block-is-executing-for-an-manhandled-exception/描述了一个“黑客”来检测是否您的代码以异常处理模式执行。它使用Marshal.GetExceptionPointers来查看异常是否“活跃”。但请记住:注意GetExceptionPointers仅针对结构化异常处理(SEH)的编译器支持公开。注意注意:此方法使用SecurityAction.LinkDemand来防止从不受信任的代码调用它;只有直接调用者需要具有SecurityPermissionAttribute.UnmanagedCode权限。如果可以从部分受信任的代码调用代码,请不要在未经验证的情况下将用户输入传递给Marshal类方法。有关使用LinkDemand成员的重要限制,请参阅Demand与LinkDemand。这个问题不是答案,而只是一个注释,我从未在实际代码中使用过“已接受”的hack,因此它在很大程度上仍未经过“野外”测试。相反,我们会这样做:DoThings(x=>{x.DoSomething();x.DoMoreThings();});其中publicvoidDoThings(Actionaction){boolsuccess=false;尝试{操作(新MyObject());犯罪();成功=真;}finally{if(!success)回滚();关键是它与问题中的“使用”示例一样紧凑,并且不使用任何hack。这样做的缺点是性能损失(在我们的例子中完全可以忽略不计),当F10踩到DoThings时,我真的希望它直接进入x.DoSomething()。两者都很小。您不能使用此信息。我会使用类似于DbTransaction类所使用的模式:也就是说,您的IDisposable类应该实现类似于DbTransaction.Commit()的方法。然后,您的Dispose方法可以根据是否调用Commit执行不同的逻辑(在DbTransaction的情况下,如果未显式提交,事务将被回滚)。您的类的用户然后将使用以下模式,类似于典型的DbTransaction:using(MyDisposableClassinstance=...){...dowhatever...instance.Commit();}//Dispose逻辑取决于Commit是否被调用。编辑我看到您编辑了您的问题以表明您已经知道这种模式(您的示例使用TransactionScope)。但是,我认为这是唯一现实的解决方案。using语句只是tryfinally块的语法糖。您可以通过最终完全编写try然后添加一个catch语句来处理您的特殊情况来获得您想要的东西:try{IDisposablex=newMyThing();}catch(Exceptionexception)//如果可能,使用更具体的异常。{x.ErrorOccurred=true;//如果你愿意,你甚至可以传递对异常的引用。}最后{x.Dispose();在MyThing中,您可以根据需要执行此操作,例如:类MyThing:IDisposable{publicboolErrorOccurred(){get;放;}publicvoidDispose(){if(ErrorOccurred){RollBack();}else{提交();这样做。它有一些代码味道。Dispose方法旨在清理非托管资源,而不是处理异常。您最好在catch块中编写异常处理代码,而不是在dispose块中编写,如果您需要共享代码,请创建一些可以从两个地方调用的有用的辅助函数。这是一个更好的方法来做你想做的事:使用(IDisposablex=newMyThing()){x.Foo();x.Bar();x.CommitChanges();}classMyThing:IDisposable{publicboolIsCommitted{get;私有集;}publicvoidCommitChanges(){//做一些需要提交的事情。已提交=真;}publicvoidDispose(){if(!IsCommitted)RollBack();这似乎不是个坏主意;它在C#/.NET中似乎并不理想。在C++中,有一个函数可以使代码检测是否由于异常而被调用。这在RAII析构函数中最为重要;析构函数选择提交还是中止是一件小事,取决于控制流是正常还是异常。我认为这是一种相当自然的方法,但缺乏内置支持(以及解决方法在道德上可疑的性质;感觉相当依赖于实现)可能意味着应该采用更传统的方法。以上是C#学习教程:如何判断.NET异常是否正在处理?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: