代码之家  ›  专栏  ›  技术社区  ›  Sandor Drieënhuizen

为什么在这个表达式树中会出现空引用异常?

  •  1
  • Sandor Drieënhuizen  · 技术社区  · 14 年前

    我有一个树表达式,如下所示:

    .Block(
        System.Object $instance,
        MyType2 $result) {
        $result = (MyType2)((MyType1)$instance).Property1;
        .Goto return { };
        .Label
        .LabelTarget useDefault:;
        $result = .Default(MyType2);
        .Label
        .LabelTarget return:;
        $result
    }
    

    public class MyType1
    {
        public MyType2 Property1 { get; set; }
    }
    
    public class MyType2
    {
    }
    

    最后,这就是我构建、编译和调用表达式树的方式(它不会像这样运行,因为我省略了一些代码来简化事情):

    object instance = new MyType1();
    
    Expression expression = ... // n => n.Property1
    
    ParameterExpression instanceParameter = Expression.Variable(
        typeof(object), "instance");
    ParameterExpression resultVariable = Expression.Variable(
        typeof(MyType2), "result");
    
    LabelTarget useDefaultLabel = Expression.Label("useDefault");
    LabelTarget returnLabel = Expression.Label("return");
    
    List<Expression> targetFragments = new List<Expression>();
    
    MemberInfo memberInfo = (MemberInfo)expression.Body.Member;
    
    MemberExpression member = ConstantExpression.MakeMemberAccess(
        Expression.Convert(instanceParameter, memberInfo.DeclaringType),
        memberInfo);
    
    targetFragments.Add(
        Expression.Assign(
            resultVariable,
            Expression.Convert(member, typeof(MyType2))));
    
    targetFragments.Add(Expression.Goto(returnLabel));
    targetFragments.Add(Expression.Label(useDefaultLabel));
    targetFragments.Add(Expression.Assign(resultVariable,
        Expression.Default(typeof(MyType2))));
    targetFragments.Add(Expression.Label(returnLabel));
    
    targetFragments.Add(resultVariable);
    
    Expression finalExpression = Expression.Block(
        new[] { instanceParameter, resultVariable },
        targetFragments);
    
    ParameterExpression parameter = Expression.Variable(typeof(object));
    
    MyType2 result = Expression.Lambda<Func<T, MyType2>>(expression, parameter)
        .Compile()(instance);
    

    对象引用未设置为对象的实例。at lambda_方法(闭包,对象)

    我认为这是因为 $result = (MyType2)((MyType1)$instance).Property1; null .

    1 回复  |  直到 14 年前
        1
  •  3
  •   Marc Gravell    14 年前

    事实是:

    ParameterExpression parameter = Expression.Variable(typeof(object));
    

    instanceParameter ,它(在代码中)只是一个未赋值的变量。

    基本上,放弃决赛 parameter 瞬时参数 作为变量:

    Expression finalExpression = Expression.Block(
        new[] { resultVariable },
        targetFragments);
    
    MyType2 result = Expression.Lambda<Func<object, MyType2>>(
          finalExpression, instanceParameter).Compile()(instance);