3

I'd like to generate this sentence using Expression trees:

o?.Value

o is an instance of whichever class.

Is there some way?

2

1 Answer 1

11

Normally, if you want to know how to construct an expression tree for some expression, you let the C# compiler do it and inspect the result.

But in this case, it won't work, because "An expression tree lambda may not contain a null propagating operator." But you don't actually need the null propagating operator, you just need something that behaves like one.

You can do that by creating an expression that looks like this: o == null ? null : o.Value. In code:

public Expression CreateNullPropagationExpression(Expression o, string property)
{
    Expression propertyAccess = Expression.Property(o, property);

    var propertyType = propertyAccess.Type;

    if (propertyType.IsValueType && Nullable.GetUnderlyingType(propertyType) == null)
        propertyAccess = Expression.Convert(
            propertyAccess, typeof(Nullable<>).MakeGenericType(propertyType));

    var nullResult = Expression.Default(propertyAccess.Type);

    var condition = Expression.Equal(o, Expression.Constant(null, o.Type));

    return Expression.Condition(condition, nullResult, propertyAccess);
}
Sign up to request clarification or add additional context in comments.

5 Comments

Just like o == null ? null : o.Value, and unlike o?.Value, this would cause o to be evaluated twice if compiled to IL, right? If so, that should probably be mentioned.
@hvd Yes. I was silently assuming it's okay, since evaluating a simple expression like o twice should not cause any issues. If you wanted to avoid that, you could create a Block that first assigns o to a temporary variable and then uses that variable. (Though that would probably not work if you want to use the expression with some LINQ provider.)
You has commented that if you want to do how to construct an expression tree for some expression, you let the C# compiler do it and inspect the result. I'd like to ask you for how to inspect these.
@Jordi By looking at it in the debugger. You could also try converting it to a string (e.g. Console.WriteLine(expression);), but the result might not tell you much (e.g. IIF((o == null), null, o.Value)).
Unfortunately, this implementation is not actually equivalent to the null-conditional operator. The actual C# operator will retrieve the possibly-null expression once, and then use that throughout. This makes it, for example, perfectly suited for raising C# events in a thread-safe way. IMHO it is erroneous and dangerous to provide a proposed implementation for the operator that doesn't have the same behavior as the actual operator.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.