.NET decimal.Negate与乘以-1的区别

10
除了可读性之外,decimal.Negate(myDecimal)myDecimal * -1之间有没有任何区别?

1
如果你对两种方法生成的IL感兴趣,可以编写一个简短的程序并使用Red-Gate的Reflector查看反编译后的IL。 - SqlRyan
@rwmnau IL代码只是问题的一个方面,可以进行讨论。请参考乔纳森的评论。我也对其他应该考虑的方面感兴趣。 - anchandra
4个回答

18

我怀疑 Negate 的存在是因为有一元负操作符 (op_UnaryNegation),而拥有代表相同功能的方法是一个好习惯,这样不支持运算符重载的语言仍然可以实现相同的结果。

因此,与其将其与 myDecimal * -1 进行比较,可能更有帮助的是将其视为编写 -myDecimal 的另一种方式。

(我相信它也被优化了——由于浮点数的工作方式,取反一个值要比普通乘法简单得多;只需要翻转一位。不需要执行任何实际的算术操作。)


8
如果你使用 .NET Reflector 查看 .NET 源代码,你会看到以下内容:(一直等到它最终打开,喝杯咖啡吧...)
public static decimal Negate(decimal d)
{
    return new decimal(d.lo, d.mid, d.hi, d.flags ^ -2147483648);
}

看起来这是一种花式说法,由于十进制内部工作的方式,它等同于-1。

如果您执行*-1,则将其映射到以下调用:

FCallMultiply(ref result, yourNumber, -1M);

这可能会产生不同的IL代码。


2

个人而言,我认为-myDecimal比其他两种写法更易读(我不是数学专家,但我相信这三种写法是等价的),但话说回来,我通常更喜欢紧凑的符号表示。

如果不选-myDecimal,我会选择Negate,因为我喜欢避免代码中出现神秘数字,虽然那里使用的-1并不是真正的神秘数字,但乍一看确实像一个。


0

来自MSDN,decimal.Negate

返回将指定的十进制值乘以负一的结果。

因此没有实际区别,但可读性很重要。


1
然而,这并没有解释实现方式。IL代码是否相同? 另外,将其作为单独的方法有什么目的? - anchandra
@anchandra - 可读性是一个很好的理由。我没有研究过IL,但如果它是相同的,我也不会感到惊讶。 - Oded
@Oded 这就是我问这个问题的原因。我“猜”它们是一样的,但我想要确认一下。 - anchandra
反射器显示Negate的代码为:return new decimal(d.lo, d.mid, d.hi, d.flags ^ -2147483648);。我怀疑这是否与myDecimal * -1-myDecimal生成的IL相同。 - Jonathan Rupp
1
还要记住,仅仅因为 IL 相同(或不同)并不意味着它将来会保持这样(即使在下一个安全补丁中也是如此)。实现可能会发生变化。 - Jonathan Rupp
@Jonathan。说得好。我对其他需要考虑的事情也很感兴趣。IL代码是要记在两种方法之间的差异的一个例子。 - anchandra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接