How can I create an expression that either throws an exception or returns a value based on a condition?

痴心易碎 提交于 2019-12-10 21:43:37

问题


I'm struggling to build an expression that if the condition is true throws an exception and if it's false that it should return a value but I'm always getting the 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()();

If I put Expression.Empty() as the third argument of the Condition it then runs but I don't get the desired result if the condition is false.


回答1:


This does it.

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 is more similar to the ternary operator. So what you were writing was more equivalent to in C#:

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

I changed your constant exception to a dynamically created one, I'm assuming that is preferred.




回答2:


Conditional expressions must return the same type from each branch. What you're trying is equivalent to

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

which is not valid. You could just cause a DivideByZeroException:

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



回答3:


Simply create a method that throws the exception for you, and has whatever type you want:

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

Then create an expression that is calling that method. This makes the act of throwing an expression an expression, rather than a statement, and allows that expression to have whatever type you want:

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));


来源:https://stackoverflow.com/questions/34773933/how-can-i-create-an-expression-that-either-throws-an-exception-or-returns-a-valu

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!