合并顺序检查

Merge Sequential Check

有一个 class A with Nullable 属性 Prop

public class A {
    int? Prop {get; set;} 
}

...

我有对象 a 类型 A 有条件的:

if (a != null && a.Prop.HasValue) { // <--
   int res = a.Prop;
}

我收到建议 "Merge sequential checks"

我不明白我怎么能那样做。 a?.Prop.HasValue 不会工作

我在这里错过了什么?

Resharper 转换您的原始逻辑:

if (a != null && a.Prop.HasValue)

进入这个:

if (a?.Prop != null)

因此,只要表达式的计算结果不为 null,该块就会执行,如果 anull,它将计算为 null(感谢 ?.) 或者如果 a.Propnull(正常)。在这两个版本中,您基本上都是在说 "do this stuff as long as both a and a.Prop have values"(或者实际上是“...没有值”)。

不过,我不确定我是否喜欢这些重构。事实上,我可以看到 JetBrains 自己并不一定认为这些是好的重构,因为它们使代码更难理解。

事实上,我认为可能具体是因为这些形式更难理解,这个 "Merge Sequential Checks" 重构在某些情况下实际上 broken,因为至少 end of April 2017 (also here),目前仍截至 2018 年 2 月底。

当表达式同时包含 || 运算符和 AnyAll LINQ 方法(以及其他情况,例如函数调用返回 bool).

给定:

var array = new[] { 1, 2, 3, 4, 5 };

Resharper 将转换为:

if (array == null || !array.Any())

进入这个:

if (!array?.Any() != true) // WRONG

原文明显"do this stuff if array is null, or if array is empty".

但是第二个版本说了什么?很难读懂,你几乎不知道它是对还是错。

!= true 实际上意味着 "do this if the expression was null or false"。好的,如果 array 为 null,我们将执行此操作,到目前为止这很好。但是,如果数组 不是 null,那么呢?

好吧,我们想在数组为空时执行这些操作。如果数组为空,则 array?.Any() 将是 false.

然后我们有!false,也就是true

然后我们有 true != truefalse

所以我们有 "if the array is empty ... don't execute the block",这与我们想要的相反。

所以 Resharper 的逻辑是倒过来的,如果 值,而不是 不是 时,块将执行一个值。

即使没有这个缺陷,代码也很难阅读,所以我觉得通常应该避免这种重构。