o?.Value的表达式树

Jor*_*rdi 2 c# linq linq-expressions null-propagation-operator

我想用Expression树生成这个句子:

o?.Value
Run Code Online (Sandbox Code Playgroud)

o 是任何一个类的实例.

有什么办法吗?

svi*_*ick 6

通常,如果要执行如何为某个表达式构造表达式树,可以让C#编译器执行此操作并检查结果.

但在这种情况下,它将无法工作,因为"表达式树lambda可能不包含空传播运算符".但是你实际上并不需要null传播运算符,你只需要一些行为类似的东西.

你可以通过创建类似如下的表达式:o == null ? null : o.Value.在代码中:

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);
}
Run Code Online (Sandbox Code Playgroud)

  • 就像 `o == null 一样?null : o.Value`,与 `o?.Value` 不同,如果编译为 IL,这会导致 `o` 被计算两次,对吗?如果是这样,那可能应该提到。 (2认同)
  • @hvd是的.我默默地认为它没关系,因为评估一个简单的表达式如"o"两次不应该引起任何问题.如果你想避免这种情况,你可以创建一个`Block`,它首先将`o`分配给一个临时变量,然后使用该变量.(如果你想在某些LINQ提供程序中使用表达式,那可能不会起作用.) (2认同)
  • 不幸的是,这个实现实际上并不等同于空条件运算符。实际的 C# 运算符将检索一次可能为空的表达式,然后在整个过程中使用它。例如,这使得它非常适合以线程安全的方式引发 C# 事件。恕我直言,为操作员提供与实际操作员行为不同的建议实现是错误且危险的。 (2认同)