为什么空传播不一致地传播Nullable <t>?

时间:2017-01-20 02:16:01

标签: c# nullable c#-6.0 null-propagation-operator

我特别提醒注意空传播,因为它与bool?bool返回方法的使用有关。例如,请考虑以下事项:

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute
{
    return property?.AttributeProvider
                    .GetAttributes(typeof(TAttribute), false)
                    .Any();
}

这不编译,并且存在以下错误:

  

无法隐式转换bool?布尔。存在显式转换(您是否错过了演员表)?

这意味着它将方法的整个主体视为bool?,因此我假设我可以在.GetValueOrDefault()之后说.Any(),但这不允许.Any()返回bool而不是bool?

我知道我可以做以下任何一项工作:

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute
{
    return property?.AttributeProvider
                    .GetAttributes(typeof(TAttribute), false)
                    .Any()
        ?? false;
}

或者

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute
{
    var any = 
        property?.AttributeProvider
                 .GetAttributes(typeof(TAttribute), false)
                 .Any();

     return any.GetValueOrDefault();
}

或者

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute
{
    return property?.AttributeProvider
                    .GetAttributes(typeof(TAttribute), false)
                    .Any()
        ?? false;
}

我的问题是,为什么我不能在.GetValueOrDefault()调用上直接调用.Any()链接?

public static bool IsAttributedWith<TAttribute>(this JsonProperty property) 
    where TAttribute : Attribute
{
    return (property?.AttributeProvider
                    .GetAttributes(typeof(TAttribute), false)
                    .Any())
                    .GetValueOrDefault();
}

我认为这是有道理的,因为此时值实际为bool?而不是bool

2 个答案:

答案 0 :(得分:6)

?.运算符之后,所有后续的调用链都被解释为条件,不仅是立即调用。所以,这段代码:

property?.AttributeProvider
         .GetAttributes(typeof(TAttribute), false)
         .Any()

解释为

property==null ? (bool?)null : property.AttributeProvider
                                       .GetAttributes(typeof(TAttribute), false)
                                       .Any()

如果您添加GetValueOrDefault()

property==null ? (bool?)null : property.AttributeProvider
                                       .GetAttributes(typeof(TAttribute), false)
                                       .Any()
                                       .GetValueOrDefault()

它会失败,因为Any()返回bool而不是bool?。因此,您需要在此处使用括号:

(property==null ? (bool?)null : property.AttributeProvider
                                        .GetAttributes(typeof(TAttribute), false)
                                        .Any())
                                        .GetValueOrDefault()

使用?.运算符时需要使用的相同括号:

(property?.AttributeProvider
          .GetAttributes(typeof(TAttribute), false)
          .Any())
          .GetValueOrDefault()

答案 1 :(得分:2)

GetValueOrDefault调用正在返回Any()方法执行,该方法返回bool。如果你想对整个身体的结果执行,你必须将它包装在括号中。

 return (property?.AttributeProvider
                .GetAttributes(typeof(TAttribute), false)
                .Any())
                .GetValueOrDefault();

空条件运算符是一个短路运算符,因此如果对象为空,则不会执行试图在对象或其任何属性或方法上执行的点右侧的任何内容。因此,为了在整个语句上执行代码,必须以某种方式包装它(括号或使用另一个对象)。