为什么 null 传播不一致地传播 Nullable<T>?

Why is null propagation inconsistently propagating Nullable<T>?

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

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

编译失败,存在以下错误:

Cannot implicitly convert bool? to bool. An explicit conversion exists (are you missing a cast)?

这意味着它将方法的整个主体视为 bool?,因此我假设我可以在 .Any() 之后说 .GetValueOrDefault() 但这不是允许 .Any() returns 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;
}

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

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

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

GetValueOrDefault 调用正在 Any() 方法的 return 上执行,return 是 bool。如果要对整个主体的结果执行,则必须将其括在括号中。

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

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

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

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() return bool 而不是 bool?。因此你需要在这里使用括号:

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

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

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