【问题标题】:Null propagation in Expression Tree表达式树中的空值传播
【发布时间】:2017-04-28 15:10:10
【问题描述】:

请参阅下面的示例代码。如何修改它以处理空值,类似于?. 运算符的工作方式?

class Program
{
    static LambdaExpression GetExpression(Expression<Func<string, string>> expr)
    {
        return expr;
    }

    static void Main(string[] args)
    {
        // I want to perform the following null propagation check
        // in the expression tree below.
        // (s as string)?.Replace("a", "o");

        var expr = GetExpression(t => t);

        var oldValue = Expression.Constant("a", typeof(string));
        var newValue = Expression.Constant("o", typeof(string));
        var mi = typeof(string).GetMethod(nameof(string.Replace), new[] { typeof(string), typeof(string) });

        var invoke = Expression.Invoke(expr, expr.Parameters);
        var call = Expression.Call(invoke, mi, oldValue, newValue);
        var lambda = Expression.Lambda(call, false, expr.Parameters);

        Console.WriteLine(lambda.Compile().DynamicInvoke("gaga"));

        // Should print empty line. Not throw!
        Console.WriteLine(lambda.Compile().DynamicInvoke(null));
    }
}

【问题讨论】:

    标签: c# lambda expression-trees


    【解决方案1】:

    你必须做两件事:

    1. 调用lambda.Compile().DynamicInvoke(null)是错误的。

      文档说明参数可以是:

      类型:System.Object[]:
      一个对象数组,作为参数传递给当前委托所代表的方法。
      - 或 -
      null,如果当前委托表示的方法不需要参数。

      因此,通过传递 null 您可以不带参数调用它,但您想使用 null 字符串参数调用:

      这就是为什么你应该将此行更改为lambda.Compile().DynamicInvoke(new object[] {null}) 或简单地lambda.Compile().DynamicInvoke((string)null)

    2. 您必须使用Expression.Condition 添加一个空条件。

    最终代码:

    var expr = GetExpression(t => t);
    var oldValue = Expression.Constant("a", typeof(string));
    var newValue = Expression.Constant("o", typeof(string));
    var mi = typeof(string).GetMethod(nameof(string.Replace), new[] { typeof(string), typeof(string) });
    
    var invoke = Expression.Invoke(expr, expr.Parameters);
    var call = Expression.Call(invoke, mi, oldValue, newValue);
    
    ConstantExpression nullConst = Expression.Constant(null, typeof(string));
    var nullCondition = Expression.Condition(Expression.Equal(invoke, nullConst),
        nullConst, call);
    
    var lambda = Expression.Lambda(nullCondition, false, expr.Parameters);
    
    object result1 = lambda.Compile().DynamicInvoke("gaga"); // =="gogo"
    object result2 = lambda.Compile().DynamicInvoke((string) null); //== null
    

    【讨论】:

    • Condition() 也适用于void 方法吗?例如。 myList?.Clear().
    猜你喜欢
    • 2017-11-24
    • 1970-01-01
    • 1970-01-01
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多