【问题标题】:Merge Sequential Check合并顺序检查
【发布时间】:2018-01-29 13:40:08
【问题描述】:

有一个类 A 具有 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 不起作用

我在这里错过了什么?

【问题讨论】:

  • a?.Prop != null 就是它所说的。那或a?.Prop.HasValue == true
  • 只需按 alt+enter 并应用建议的更改,如果您可以应用建议的更改,不知道为什么要问“我该怎么做”(据我所知,您可以应用所有建议的更改,并且当然是这个)。
  • 从左到右解析if语句。因此,如果 a 为 null,则永远不会执行 a.Prop.HasValue。
  • 这些 cmets 应该是答案... ;)

标签: c# .net resharper


【解决方案1】:

Resharper 转换你原来的逻辑:

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

进入这个:

if (a?.Prop != null)

因此,只要表达式不计算为null,块就会执行,如果anull(感谢?.)或@987654331,它将计算为null @ 是 null (正常)。在这两个版本中,您基本上是在说“只要 aa.Prop 都有值就做这些事情”(或者真的是“......没有值”)。

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

事实上,我认为可能特别是因为这些形式更难理解,这种“Merge Sequential Checks”重构实际上在某些情况下损坏,因为至少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

原文显然是“如果arraynull,或者array 为空,则执行此操作”。

但是第二个版本是怎么说的呢?它很难读懂,你几乎无法判断它是对还是错。

!= true 实际上意味着“如果表达式是nullfalse,则执行此操作”。好的,所以如果array 为空,我们会这样做,到目前为止这很好。但是,如果数组不为空,那又是什么呢?

好吧,如果数组是空的,我们想做这些事情。如果数组为空,则array?.Any() 将为false

然后我们有!false,即true

然后我们有true != true,即false

所以我们有“如果数组为空......不要执行块”,这与我们想要的相反。

所以 Resharper 已经把逻辑倒退了,如果有 一个值,而不是如果有 没有 一个值,则该块将执行。

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

【讨论】:

    猜你喜欢
    • 2023-03-16
    • 2018-11-13
    • 2017-12-31
    • 1970-01-01
    • 1970-01-01
    • 2011-09-10
    • 2019-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多