为什么空条件运算符在==和.Equals()中表现不同?

3

我有如下代码,工作正常:

var firstChild = token.First as JProperty;
bool isHref = token.Children().Count() == 1
           && firstChild?.Name == "href";

我希望将字符串比较变为不区分大小写,因此我将其更改为:

var firstChild = token.First as JProperty;

bool isHref = token.Children().Count() == 1
           && firstChild?.Name.Equals("href", StringComparison.OrdinalIgnoreCase);

现在编译器给了我一个错误:

运算符&&不能用于类型为'bool'和'bool?'的操作数

我可以通过将其合并为false来修复此错误,例如:

bool isHref = token.Children().Count() == 1
         && (firstChild?.Name.Equals("href", StringComparison.OrdinalIgnoreCase) ?? false);

但我好奇为什么编译器不喜欢第一个空值条件语法。


2
如果你这样做String.Equals(firstChild?.Name, "href", StringComparison.OrdinalIgnoreCase);会发生什么? - Habib
1
原因是 ?. 可能返回 null 或者值。在你的情况下,由于有一个返回 bool 的方法,它只能返回 Nullable<bool> 来容纳实际结果的 true/false 或者在 firstChild 为空时返回 null。因此,表达式的返回类型是 Nullable<bool>,而且由于不能同时应用 &&,所以会出现错误。 - Habib
1
请注意,您可以将 &boolbool? 一起使用。但结果将是一个 bool?。由于短路的原因,&& 不起作用。短路不起作用是因为如果 bool?null,则希望得到一个 null 结果,但是如果第一部分是 false,则甚至不会评估第二部分。 - juharr
问题归结为firstChild为空。在这种情况下,整个表达式将为null(而不是一个直接的布尔值)。 - Millie Smith
2个回答

5

让我们简化到基本要素。

string x = null, y = null;

// this is null.  b1 is bool?
var b1 = x?.Equals(y); 

// b2 is bool
// this is true, since the operator doesn't require non-null operands
var b2 = x == y;

基本上,.Equals() 需要对一个非空对象进行操作。这与 == 不同,它是静态绑定而不是动态分派。


谢谢,这正是我在寻找的解释! - Nate Barbettini

2

第一个表达式返回 null 或 bool

如果 firstChild 为 null,则返回值将为 null,并且无法在 if 条件中使用

firstChild?.Name.Equals("href", StringComparison.OrdinalIgnoreCase)

将会与之相同

firstChild == null ? null : firstChild.Name.Equals("href", StringComparison.OrdinalIgnoreCase)

这很有道理,但仍然无法解释为什么 && firstChild?.Name == "href" 可以编译通过。 - Nate Barbettini
3
firstChild?.Name的结果是null或字符串,然后将其与“href”进行比较,结果只会得到一个true/false值。 - Khatibzadeh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接