【问题标题】:Does Roslyn omit multiplication by 1 in cases where a value is known to be 1 at compile time?在编译时已知值为 1 的情况下,Roslyn 是否省略乘以 1?
【发布时间】:2019-09-09 14:01:16
【问题描述】:

请记住similar question 在变量硬编码为 1 的情况下,C#/Roslyn 是否省略乘以 1?类似问题的答案表明 Roslyn 会在编译时将 var x = 5 * 1 转换为 var x = 5,但我想知道这是否适用于更复杂的示例。

例子:

var baseAmount = 25.10M;
var multiplier = 1;
var total = baseAmount * multiplier; // does this become just "baseAmount"?

最终,我试图确定添加 * 1 或等效项是否会导致大规模的性能影响(代码命中数百万次)。在这种情况下,使用 * 1 乘法明确和冗长将为代码库的新手带来更易读的“自我注释”代码。

【问题讨论】:

  • 由于baseAmount 是一个小数,乘法仍然会进行。如果它是一个 int,它可能会被省略。但是,正如我在之前的评论中所暗示的那样,它几乎可以肯定是不相关的。 “数百万”次不会引起注意。
  • 您是否尝试对其进行基准测试?
  • 当然,但我倾向于从这里更有经验的开发人员那里获得更多信息(例如,Roslyn 所做的取决于 baseAmount 是小数(或我假设为双精度)还是整数)。我可能会错过。

标签: c# compilation


【解决方案1】:

看下面代码的反汇编:

public int test()
{
    int baseAmount = 25;
    var multiplier = 1;
    var total = baseAmount * multiplier;
    return total;
}

你可以看到imul还在:

将乘数替换为常数 1 会移除 imul:

将 baseAmount 的类型从 int 更改为 Decimal 会创建更复杂的汇编代码。带乘数变量:

没有乘数:

查看汇编代码,似乎在这两种情况下都调用了 multiply 子例程(黄色箭头旁边)。所以在这种情况下编译器不会优化常量 1。

【讨论】:

  • 因此,如果我理解正确,硬编码为 1 的变量不会被识别为“1”,因此会被编译器省略,例如baseAmount * multiplier 在运行时被如此评估,而 baseAmount * 1 在运行时会变成 baseAmount 吗?如果是这种情况,您能否使用此信息编辑您的答案?
  • @Elias 现在试试decimal baseAmount = 25M;,看看为什么你的答案不正确/不完整。
  • jspinella 是的,这是正确的。我已经用信息更新了我的答案。 @DavidG 正如您所提到的,当 baseAmount 是小数时,编译器不会优化常量。
猜你喜欢
  • 2014-04-12
  • 1970-01-01
  • 2018-05-04
  • 1970-01-01
  • 2022-12-21
  • 1970-01-01
  • 1970-01-01
  • 2017-02-06
  • 1970-01-01
相关资源
最近更新 更多