我的方法如下:
public TResult DoSomethingWithLogging<TResult>(Func<TResult> someAction)
{
try
{
return someAction.Invoke();
}
catch (Exception ex)
{
LogException(ex)
throw;
}
此方法使用如下:
var result = DoSomethingWithLogging(() => Foo());
我还想记录Foo()
内捕获的异常。我无法在throw
内的catch
内使用Foo
。
我怎样才能抓住这些例外?
示例:
public static string Foo()
{
try
{
return "Foo";
}
catch (Exception)
{
// I have to log this exception too without adding anything to Foo
return "Exception caught";
}
}
答案 0 :(得分:17)
您可以绑定到FirstChanceException
事件。以下是您修改的代码以证明这一点:
using System;
using System.Runtime.ExceptionServices;
public class Program
{
public static void Main()
{
AppDomain.CurrentDomain.FirstChanceException +=
(object source, FirstChanceExceptionEventArgs e) =>
{
Console.WriteLine("FirstChanceException event raised in {0}: {1}",
AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
};
Console.WriteLine("Hello World");
Console.WriteLine(DoSomethingWithLogging(() => Foo()));
}
public static TResult DoSomethingWithLogging<TResult>(Func<TResult> someAction)
{
try
{
return someAction.Invoke();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
throw;
}
}
public static string Foo()
{
try
{
throw new Exception("This will be caught");
return"Foo";
}
catch (Exception) //I have to log this exception too without adding anything too Foo
{
return "Exception caught";
}
}
}
作为一项规则,除了调试方案之外,我会对此非常谨慎。一旦它被捕获,它不应该被更高的代码视为异常。 (当然,首先捕获它可能是一个逻辑错误,因此这确实在调试方案中有一些价值)。
多线程案例也存在并发症。上面的代码演示了FirstChanceException
如何工作,但是如果你在调用之前附加了,然后在它之后分离,它仍会被其他线程上的任何异常触发。过滤掉那些可能会很棘手。我可能首先考虑查看调用堆栈,但我不确定这是最好的方法。
答案 1 :(得分:4)
您可以通过处理AppDomain.FirstChanceException
event:
在运行时在应用程序域中搜索调用堆栈中的异常处理程序之前,在托管代码中抛出异常时发生。
请参阅Catching First Chance Exceptions in Managed Code without being debugged。
答案 2 :(得分:2)
我认为你的做法是错误的。假设foo的实现是一个非常糟糕的主意。 (就像评论中提到的JDM一样,这是一种代码味道,它会让你遇到麻烦)
重新设计方法的一种方法是使用事件
class FooClass {
public event SkippedWorkEventHandler SkippedWork;
public void Foo() {
try {
/* some code */
} catch (Exception ex) {
if (SkippedWork != null) {
/* pass in the relevant data to eventargs */
SkippedWork(this, EventArgs.Empty)
}
}
}
public void DoSomethingWithFoo() {
SkippedWork += new LogSkippedWorkEventHandler
try {
Foo()
} catch (Exception ex) {
/*handle uncaughed exceptions here */
}
}
}
这样做的原因是从外面我不能保证我使用try / catch来检测foo中发生的事情。如果我的测试失败,我可能会将其重写为简单的if check并返回。 foo的结果是相同的,除非现在没有记录您的异常。
通过公开活动,您可以允许任何对某些事物感兴趣的人(基于您的评论的跳过的行)对其做出反应。并且你签了一份合同,说你将荣幸/举起这个活动。