I've been trying to create a custom ExpressionVisitor that would generate an expression that (optionaly) throws a NullReferenceException on the first null value. The DebugView of the expression looks fine to me but it doesn't work as exptecte (by me). I thought it would first throw the
.Throw .New System.NullReferenceException("c3")
because the test variable is null but instead this one is thrown
.Throw .New System.NullReferenceException("p")
I cannot understand why it executes the statements backwards. Shouldn't it execute the innermost If first?
DebugView:
.Block() {
    .If (.Block() {
        .If (.Constant<ExpressionTrees.Program+<>c__DisplayClass0_0>(ExpressionTrees.Program+<>c__DisplayClass0_0) == null) {
            .Throw .New System.NullReferenceException("c3")
        } .Else {
            .Default(System.Void)
        };
        .Constant<ExpressionTrees.Program+<>c__DisplayClass0_0>(ExpressionTrees.Program+<>c__DisplayClass0_0).c3
    } == null) {
        .Throw .New System.NullReferenceException("p")
    } .Else {
        .Default(System.Void)
    };
    (.Constant<ExpressionTrees.Program+<>c__DisplayClass0_0>(ExpressionTrees.Program+<>c__DisplayClass0_0).c3).p
}
My complete test code:
namespace ExpressionTrees
{
    class c1
    {
        public c2 c2 { get; set; }
    }
    class c2
    {
        public c3 c3 { get; set; }
    }
    class c3
    {
        public string p { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            c3 c3 = null; 
            var test_c3 = NullGuard.Check(() => c3.p, true);
        }
    }
    public static class NullGuard
    {
        public static T Check<T>(Expression<Func<T>> expression, bool canThrowNullReferenceException = false)
        {
            var nullGuardVisitor = new NullGuardVisitor(canThrowNullReferenceException);
            var nullGuardExpression = nullGuardVisitor.Visit(expression.Body);            
            var nullGuardLambda = Expression.Lambda<Func<T>>(nullGuardExpression, expression.Parameters);
            var value = nullGuardLambda.Compile()();
            return value;
        }
    }
    public class NullGuardVisitor : ExpressionVisitor
    {
        private readonly bool _canThrowNullReferenceException;
        internal NullGuardVisitor(bool canThrowNullReferenceException)
        {
            _canThrowNullReferenceException = canThrowNullReferenceException;
        }
        protected override Expression VisitMember(MemberExpression node)
        {
            var expression = Visit(node.Expression);
            // expression == null
            var expressionEqualsNull = Expression.Equal(expression, Expression.Constant(null, expression.Type));
            if (_canThrowNullReferenceException)
            {
                var nullReferenceExceptionConstructorInfo = typeof(NullReferenceException).GetConstructor(new[] { typeof(string) });
                // if (expression == null) { throw new NullReferenceException() } else { node }
                var result = 
                    Expression.Block(
                        Expression.IfThen(
                            expressionEqualsNull,
                            Expression.Throw(Expression.New(nullReferenceExceptionConstructorInfo, Expression.Constant(node.Member.Name)))
                        ),
                        node
                    );
                return result;
            }
            else
            {
                var result = Expression.Condition(
                    expressionEqualsNull,
                    Expression.Constant(null, expression.Type),
                    node);
                return result;
            }
        }
    }
}
 
     
    