Expression.Convert within Expression.TryCatch

c# expression-trees

Question

To a code snippet from the Effort library that creates an expression tree to do a conversion and assign the result to a property, I'm attempting to add some error-handling.

The issue with the current code is that when attempting to assign null to a property with a value type, a NullReferenceException is raised when this expression is called at runtime. Since I don't know anything about the property that was being attempted to be assigned in this scenario, I want to throw a more particular exception.

The following is my initial effort to simply wrap this logic in a try/catch block, with an exception being thrown in the event that the conversion fails. In time, I would expand the details of the 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"))))));

In my opinion, I'm attempting to accomplish the following:

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

It now raises an ArgumentException at runtime with the message "Body of catch must have the same type as body of try," however. Why am I doing this wrong? Even though the Block in the Catch expression won't ever be touched because of the Throw, do I still need to include it to "return" some fictitious value?

Or am I going about this completely wrong?

1
6
5/10/2017 10:59:41 PM

Accepted Answer

In typical C# code, a method must either throw an exception or return a value.

With Expression s, however, it functions somewhat differently: each expression has a return type, and in the case ofTryCatch Upon returning from thetryExpression must be the same as any of the return types fromcatchExpression s.

Your situation's kind of thetry is int nonetheless, the nature of thecatch is void therefore they cannot be combined. In order to correct this, you must either alter the type of thetry to void can alter the kind of thecatch to int .

To modify the kind oftry to void , you may use an abundance ofExpression.Block() to define the block type (typically, it's the same as the type of the block's last expression):

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

To modify the kind ofcatch to int it would be necessary to modify the type of theThrow expression. And since for aThrow expression, There is an overload that enables return type specification., any return type is acceptable (because it doesn't really return):

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

I believe that altering the kind oftry is logically simpler since the whole phrase is not intended to return anything.

8
5/15/2014 12:18:28 PM


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow