ReSharper `MergeSequentialChecks` 和 `MergeSequentialChecksWhenPossible` 之间有什么区别?

What's the difference between ReSharper `MergeSequentialChecks` and `MergeSequentialChecksWhenPossible`?

我想弄清楚这两条规则有什么区别?

文档没有说明第二个。 https://www.jetbrains.com/help/resharper/2016.1/MergeSequentialChecks.html

我不太清楚这是什么意思WhenPossible

如果 ReSharper 建议应用第一条规则并合并我的顺序检查,那么它确实是可能的。怎么可能不行?

这是要检查的代码示例。

public class Person
{
    public string Name { get; set; }
    public IList<Person> Descendants { get; set; }
}

public static class TestReSharper
{
    // Here `MergeSequentialChecks` rule is triggered for both `&&` operands.
    public static bool MergeSequentialChecks(Person person)
    {
        return person != null && person.Descendants != null && person.Descendants.FirstOrDefault() != null;
    }

    // Here `MergeSequentialChecksWhenPossible` rule is triggered.
    public static bool MergeSequentialChecksWhenPossible1(Person person)
    {
        return person != null && person.Descendants.Any();
    }

    // Here `MergeSequentialChecksWhenPossible` rule is triggered.
    public static bool MergeSequentialChecksWhenPossible2(Person person)
    {
        return person.Descendants != null && person.Descendants.Any();
    }
}

带有“(如果可能)”标签的代码检查背后的想法很简单:我们决定不建议使用默认 R# 设置进行可能的代码转换,因为生成的代码可能会导致可读性降低或变得更难理解。关于建议或不建议的决定是通过临时试探法完成的。

当我们首次实施与 C# 6.0 相关的代码建议和转换并在可供我们使用的大型解决方案中审查它们的结果时,我们决定将近 ~2/3 的检查如 "Merge sequential checks" / "Use null propagation" 不应建议进行代码转换。例如,我们认为在这样的代码的情况下:

if (node != null && node.IsValid()) { ... }

...使用 ?. 运算符和引入 "lifted" operator==(bool, bool) 运算符对 bool? 类型的值没有真正的好处:

if (node?.IsValid() == true) { ... }

此外,不同的开发者对如何检查类型 bool? 的值是否为 true 有不同的看法(有些人更喜欢使用 ?? false,但这会使生成的代码 even?.more ?? questionable).

因此,在上述情况下,顺序检查的合并肯定是 "possible",但我们不会推荐使用默认 R# 设置(正确的默认设置是一项巨大的责任),让用户能够通过启用相同代码检查的“(如果可能)”版本来查看所有情况。据我所知,目前我们只在 "Merge sequential checks" 检查中检查是否不产生提升的布尔检查,其他检查有更多的启发式,例如:

if (stringBuilder != null) { // "Use null propagation"
  stringBuilder.Append("hello");
}

上面的代码值得建议使用条件调用运算符:

stringBuilder?.Append("hello");

虽然连续两次或多次使用条件调用是有问题的...

if (stringBuilder != null) { // no suggestion
  stringBuilder.Append("hello");
  stringBuilder.Append("world");
  stringBuilder.Append("!!!");
}

p.s。上下文操作 "Merge sequential checks" / "To null propagation" 在转换可能时始终 启用,尽管代码检查的状态及其严重性。