我如何创建一个表达式,它要么抛出异常,要么根据条件 returns 一个值?
How can I create an expression that either throws an exception or returns a value based on a condition?
我正在努力构建一个表达式,如果条件为真则抛出异常,如果条件为假则应该 return 一个值,但我总是得到 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
的第三个参数,它就会运行,但如果条件为假,我得不到想要的结果。
这样就可以了。
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;
我将您的常量异常更改为动态创建的异常,我假设这是首选。
条件表达式必须return来自每个分支的相同类型。你正在尝试的相当于
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));
只需创建一个为您抛出异常并具有您想要的任何类型的方法:
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));
使用带有两个参数的Expression.Throw,第二个参数包含结果表达式值的类型。
我正在努力构建一个表达式,如果条件为真则抛出异常,如果条件为假则应该 return 一个值,但我总是得到 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
的第三个参数,它就会运行,但如果条件为假,我得不到想要的结果。
这样就可以了。
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;
我将您的常量异常更改为动态创建的异常,我假设这是首选。
条件表达式必须return来自每个分支的相同类型。你正在尝试的相当于
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));
只需创建一个为您抛出异常并具有您想要的任何类型的方法:
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));
使用带有两个参数的Expression.Throw,第二个参数包含结果表达式值的类型。