如何创建一个抛出异常或根据条件返回值的表达式?

时间:2016-01-13 18:06:04

标签: c# expression-trees

我正在努力构建一个表达式,如果条件为true则抛出异常,如果它为false则应该返回一个值,但我总是得到ArgumentException

var expr =
    Expression.Condition(
        Expression.Equal(Expression.Constant(0), Expression.Constant(0)),
        Expression.Throw(Expression.Constant(new DivideByZeroException())),
        Expression.Constant(1));
var lambda = Expression.Lambda<Func<int>>(expr);
var result = lambda.Compile()();

如果我将Expression.Empty()作为Condition的第三个参数,那么它会运行,但如果条件为假,我就无法获得所需的结果。

4 个答案:

答案 0 :(得分:4)

就是这样。

var expr =
    Expression.Block(
        Expression.IfThen(
            Expression.Equal(Expression.Constant(1), Expression.Constant(1)),
            Expression.Throw(
                Expression.New(typeof(DivideByZeroException))
            )
        ),
        Expression.Constant(1)
    );
var lambda = Expression.Lambda<Func<int>>(expr);
var result = lambda.Compile()();

Conditional更类似于三元运算符。所以你写的更像是在C#:

return (0 == 0) ? throw new DivideByZeroException() : 1;

我将常量异常更改为动态创建的异常,我认为这是首选。

答案 1 :(得分:1)

条件表达式必须从每个分支返回相同的类型。你正在尝试的是等同于

var x = 0==0 ? throw new DivideByZeroException() : 1;

无效。您 只能导致 DivideByZeroException

var expr =
Expression.Condition(
    Expression.Equal(Expression.Constant(0), Expression.Constant(0)),
    Expression.Divide(Expression.Constant(1), Expression.Constant(0)),
    Expression.Constant(1));

答案 2 :(得分:1)

只需创建一个为您抛出异常的方法,并且具有您想要的任何类型:

public static T ThrowHelper<T>(Exception e)
{
    throw e;
}

然后创建一个调用该方法的表达式。这使得将表达式抛出表达式而不是语句,并允许该表达式具有您想要的任何类型:

var throwMethod = typeof(TheClassThrowIsIn)
    .GetMethod("ThrowHelper", BindingFlags.Static)
    .MakeGenericMethod(typeof(int));
var expr =
    Expression.Condition(
        Expression.Equal(Expression.Constant(0), Expression.Constant(0)),
        Expression.Call(throwMethod, Expression.Constant(new DivideByZeroException())),
        Expression.Constant(1));

答案 3 :(得分:0)