7

我正在尝试向Effort 库中的代码块添加一些错误处理,该代码块生成表达式树以执行转换并将结果分配给属性。

现有代码的问题是,当尝试将 null 分配给具有值类型的属性时,在运行时调用此表达式时会引发 NullReferenceException。在这种情况下,我没有关于它试图分配的属性的信息,所以我想抛出一个更具体的异常。

以下是我第一次尝试将此逻辑封装在 try/catch 块中,如果转换失败则抛出异常。最终我会向 InvalidOperationException 添加更多信息。

blockElements.Add(
    Expression.TryCatch(
        Expression.Assign(
            Expression.Property(result, this.Properties[i]),
            Expression.Convert(
                Expression.ArrayIndex(parameter, Expression.Constant(i)),
                this.Properties[i].PropertyType)),
        Expression.Catch(typeof(NullReferenceException),
            Expression.Throw(Expression.Constant(
            new InvalidOperationException("Unhandled exception"))))));

在我看来,这就是我想要做的:

try
{
    Property = (int)value;
}
catch (NullReferenceException)
{
    throw new InvalidOperationException("Unhandled exception");
}

但是在运行时,该表达式现在会引发 ArgumentException,并显示消息“catch 的主体必须与 try 的主体具有相同的类型”。我在这里做错了什么?我是否需要在 Catch 表达式中创建一个 Block 来“返回”一些虚拟值,即使它永远不会因为 Throw 而被击中?

还是我以完全错误的方式处理这个问题?

4

1 回答 1

10

在普通的 C# 代码中,作为一个整体的方法必须要么返回一个值,要么抛出一个异常。

对于Expressions,它的工作方式有点不同:每个表达式都有一个返回类型,在 s 的情况下TryCatch,the 的返回类型必须与任何stry Expression的返回类型相同。catch Expression

在您的情况下,tryis 的类型,但 is的int类型,所以它们不能一起使用。要解决此问题,您需要更改 to 的类型,或更改to的类型。catchvoidtryvoidcatchint

要更改tryto的类型void,您可以使用允许您指定块的类型的重载Expression.Block()(通常,它与块中最后一个表达式的类型相同):

Expression.TryCatch(
    Expression.Block(
        typeof(void),
        Expression.Assign(…)),
    Expression.Catch(
        typeof(NullReferenceException),
        Expression.Throw(
            Expression.Constant(
                new InvalidOperationException("Unhandled exception")))))

要更改catchto的类型int,您需要以某种方式更改Throw表达式的类型。而且由于对于Throw表达式,任何返回类型都可以是有效的(因为它实际上并不返回),所以有一个重载可以让您指定返回类型

Expression.TryCatch(
    Expression.Assign(…),
    Expression.Catch(
        typeof(NullReferenceException),
        Expression.Throw(
            Expression.Constant(
                new InvalidOperationException("Unhandled exception")),
            typeof(int))))

我认为更改的类型在try概念上更清晰,因为您实际上并不想从整个表达式中返回任何内容。

于 2013-01-16T19:45:41.963 回答