无法捕获Invoke在已编译表达式上抛出的异常

时间:2010-02-26 11:54:56

标签: c# .net exception lambda

在课堂上:

private Func<T, object> pony;

在我的职能中:

object newValue;
try {
  newValue = pony.Invoke(model as T); // This is the line where I get an exception!
} catch (Exception exception) {
  // This code is never run, even though I get an exception two lines up!
  if(exception is DivideByZeroException) throw new DivideByZeroException("Division by zero when calculating member " + GetMemberName(), exception);
  throw;
}

我希望在扔掉它们时会遇到异常,但我会在DivideByZeroException行上找到newValue = pony.Invoke(model as T);。为什么是这样?我能为此做些什么吗?

这是在Cassini中运行的asp.net mvc2应用程序。

如果我在Visual Studio 2008中选择“开始调试”,则会捕获错误,并使用额外信息重新生成错误!

问题是我显然不明白内部异常是如何运作的。异常被捕获,但之后只显示内部异常,这是一个完全不同的问题。

3 个答案:

答案 0 :(得分:1)

以下代码对我有用(这是在C#控制台应用程序中,虽然我不知道为什么它与ASP.NET的工作方式不同):

class Program
{
    static void Main(string[] args)
    {
        var foo = new Foo<int>();
        try
        {
            Console.WriteLine("Calling function");
            foo.DoStuff(5);
        }
        catch(Exception ex)
        {
            Console.WriteLine("Caught exception: " + ex.ToString());
        }
        finally
        {
            Console.WriteLine("In finally block");
        }
    }
}

class Foo<T>
{
    private Func<T, object> pony;

    public Foo()
    {
        this.pony = m =>
        {
            throw new DivideByZeroException("Exception!");
        };
    }

    public object DoStuff(T o)
    {
        return this.pony.Invoke(o);
    }
}

这会将命令行中的异常内容打印出来,如预期的那样。

答案 1 :(得分:1)

从编译表达式抛出的异常通常由try .. catch构造处理,所以我希望你的代码中还有其他一些问题。如果您尝试以下代码,它的行为与预期一致:

Expression<Func<int, int>> f = x => 10 / x;
Func<int, int> fcompiled = f.Compile();
try {
  Console.WriteLine(fcompiled(0));
} catch (DivideByZeroException e) {
  Console.WriteLine("Divison by zero");
}

作为旁注,您应该使用单独的DivideByZeroException来处理catch(就像我在我的示例中所做的那样)。这是一种更清晰,更推荐的方法来捕获不同类型的异常。

在没有调试的情况下运行应用程序时,您是否可以检查异常是否真的未处理(例如,通过向catch块添加一些调试打印)?运行应用程序时会打印什么异常(毕竟,您的代码在任何情况下都会重新抛出一些异常,因此输出可能不清楚。)

答案 2 :(得分:0)

好吧,在编译表达式中执行的代码显然会生成DivideByZeroException,对吧。有些东西试图除以零。那你还期待什么?

请注意,调试器(尤其是VS)可能会因异常而中断,因此您应该确保继续运行应用程序,它应该可以很好地到达catch块。