【问题标题】:Why do I get a null reference exception in this expression tree?为什么我在这个表达式树中得到一个空引用异常?
【发布时间】:2010-08-01 23:33:10
【问题描述】:

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

.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);

但是调用会引发以下异常:

对象引用未设置为对象的实例。在 lambda_method(闭包,对象)

我认为这是因为 $result = (MyType2)((MyType1)$instance).Property1; 分配而发生的,但我不明白为什么,因为传递给表达式的实例不是 null。

【问题讨论】:

    标签: c# .net c#-4.0 lambda expression-trees


    【解决方案1】:

    事实是:

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

    是定义后所有的body应该是线索;本质上,您甚至根本没有看您传入的对象;您只查看instanceParameter,它(在您的代码中)只是一个未分配的变量。

    基本上,删除最后的parameter 声明,并且不要将instanceParameter 声明为变量:

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

    【讨论】:

    • 谢谢马克,成功了。我确信编译器无法区分传递的参数(如果我传递了其他参数),所以我将instanceParameter 添加到块中。但是现在我很明显可以从Func 类型参数中看到它。
    • 再次感谢您帮助我。这个问题与我在blog.subspace.nl/post/… 写的一篇博文密切相关,这可能会引起人们的兴趣。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-13
    • 2011-04-14
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多