3

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.

t3chb0t
  • 16,340
  • 13
  • 78
  • 118

4 Answers4

4

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.

Shlomo
  • 14,102
  • 3
  • 28
  • 43
  • Pefect. It works ;-) thank you... I've been searching msdn for an hour and didn't see the `If`s... but even if I have found it the `Block` expression makes the magic. – t3chb0t Jan 13 '16 at 18:30
  • I'm upgrading the null-reference-visitor from [this](http://stackoverflow.com/questions/30488022/how-to-use-expression-tree-to-safely-access-path-of-nullable-objects) question to optionally throw `NullReferenceExeption`s... now it does ;-D – t3chb0t Jan 13 '16 at 18:34
1

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));
D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • I guess I picked the wrong exception. It was there just to throw something other then the `NullReferenceExeption` or any other common one. Thanks anyway for the suggestion, it's however not what I was looking for this time ;-) – t3chb0t Jan 13 '16 at 18:32
1

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));
Servy
  • 202,030
  • 26
  • 332
  • 449
0

Use Expression.Throw with two parameters, second parameter contains type of a result expression value.

https://learn.microsoft.com/en-us/dotnet/api/system.linq.expressions.expression.throw?view=netframework-4.7.2#System_Linq_Expressions_Expression_Throw_System_Linq_Expressions_Expression_System_Type_

  • 1
    Generally, links [should be accompanied by usage notes, a specific explanation of how the linked resource is applicable to the problem, or some sample code](http://meta.stackoverflow.com/a/251605), or if possible all of the above. – DCCoder Sep 25 '20 at 06:46
  • I already know how to do it. The quesiton is about how throw conditionally. – t3chb0t Sep 25 '20 at 17:04