更改此条件,使其不总是评估为“真”

Posted

技术标签:

【中文标题】更改此条件,使其不总是评估为“真”【英文标题】:Change this condition so that it does not always evaluate to 'true' 【发布时间】:2018-02-10 07:30:38 【问题描述】:

SonarQube 为什么抱怨这部分代码?

我检查了这段代码,但这个值并不总是正确的。

public static void WriteJson(object value)

    decimal decimalValue = ((decimal?)value).Value;
    int intValue = (int)decimalValue;
    if (decimalValue == intValue)
        Console.WriteLine(intValue);
    else
        Console.WriteLine(decimalValue);
    Console.ReadKey();

SonarQube 为什么抱怨这个?

【问题讨论】:

除非 SonarQube 有一根魔杖知道你将在运行时传入什么,否则这是错误的。而且我不喜欢欺骗你的工具,尤其是当它们建议重构会破坏代码时。 疯狂猜测:SonarQube 看到decimalValue 转换为int 并返回到decimal,因此它假设(错误地)该值((decimal)intValue)是原始的decimalValue - 这意味着条件是总是正确的。如果它演员而不是转换,那将是正确的。 【参考方案1】:

误报与我们的数据流分析引擎中的缺陷有关 - 它没有考虑浮点数和整数之间的转换(目前),并且无法识别浮点数何时被截断。

我将尝试详细说明一下:数据流分析引擎会跟踪分析方法中的局部变量的值,当为变量分配新值时,引擎会创建一个表示实际值的特殊对象.当您将一个变量分配给另一个变量时,该对象保持不变。例如:

var x = 5; // the symbol of x is associated with value_0
var y = x; // the symbol of y is associated with value_0
if (x == y) // value_0 is compared with value_0 --> always true

我们分配的值不包含类型信息(还),我们无法检测到(还)像您这样的情况的变化:

var x = 5.5; // the symbol of x is associated with value_0
var y = (int)x; // the symbol of y is associated with value_0 (wrong)
if (x == y) // false positive

我们会生成误报,但它们相对较少,因为大多数类型转换不会生成新值。

感谢您的反馈,我们将调查in the near future。

【讨论】:

【参考方案2】:

看起来 SonarQube 检测到您正在为两个变量分配相同的值,假设传递给方法的值等于 2

 1. decimal decimalValue = 2 
 2. int intValue = (int)decimalValue;

因此decimalValue = 2intValue = 2

C# 编译器显然会将其转换为int,因此如果您通过2.5if 比较将不会始终评估为true。但很可能 SonarQube 只是不知道演员阵容。所以它假定总是正确的。

【讨论】:

【参考方案3】:

我不是 SonarQube 的专家,但我猜这是因为 SonarQube 检测到您将 intValue 设置为 decimalValue 的舍入形式。然后你又将decimalValueintValue 的十进制形式进行比较。因此,在许多情况下,它会返回“true”。 要查看结果如何,假设 decimalValue 为“123.0”。然后,intValue 将恰好是“123”。然后,我们用“if”语句比较“123.0”(decimalValue的值)和“123.0”(intValue转换为十进制后的值),返回true。这将适用于所有整数。

【讨论】:

另一方面,如果value为123.4,则条件为假

以上是关于更改此条件,使其不总是评估为“真”的主要内容,如果未能解决你的问题,请参考以下文章

如何避免“更改此条件,使其不总是评估为“假””

处理空条件(在声纳中更改此条件,使其不总是评估为“假”)

声纳误报,“改变条件,使其并不总是评估为真。”

“更改此条件,使其不会总是评估为假” - SonarQube

将对象推入数组并使其不可变

代码优化 - 删除这个总是评估为“真”的表达式