“十进制”类型的有趣行为在 C# 中
如果我们将填充声明为常量十进制,则填充不起作用。
mymoney = 1.2 而你的钱 = 1.20,如何解释这种行为?
class Program
{
static void Main(string[] args)
{
decimal balance = 1.2m;
const decimal ConstPadding = 0.00m;
decimal padding = 0.00m;
decimal mymoney = decimal.Round(balance + ConstPadding, 2);
decimal yourmoney = decimal.Round(balance + padding, 2);
Console.WriteLine(mymoney); // 1.2
Console.WriteLine(yourmoney); //1.20
}
}
If we declare padding as const decimal, the padding is not working.
mymoney = 1.2 and your money = 1.20, how can this behavior be explained?
class Program
{
static void Main(string[] args)
{
decimal balance = 1.2m;
const decimal ConstPadding = 0.00m;
decimal padding = 0.00m;
decimal mymoney = decimal.Round(balance + ConstPadding, 2);
decimal yourmoney = decimal.Round(balance + padding, 2);
Console.WriteLine(mymoney); // 1.2
Console.WriteLine(yourmoney); //1.20
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果我没记错的话,编译器不会对常量小数进行加法,因为它为零。
很快就会发布证据。
乔恩·斯基特(Jon Skeet)在上面的回答中给出了证明。
If I'm not mistaken the complier isn't doing the addition with the constant decimal because it is zero.
Will post proof shortly.
Proof shown by Jon Skeet answer above.
编译器“知道”向值添加零“不应该”改变该值 - 因此它对此进行了优化。现在可以说,考虑到十进制加法的性质,这是一种无效的优化,但如果您查看生成的代码,您会发现
mymoney
的计算不涉及加法。老实说,我不认为我会尝试使用添加 0.00m 作为确保特定比例的方法。您可以使用
decimal.GetBits
和 构造函数执行相反的操作 - 但我认为这不是很好。您确实需要这种“两位小数”形式作为中间值,还是仅用于演示?如果是后者,我会查看格式字符串。
The compiler "knows" that adding zero to a value "shouldn't" change the value - so it optimizes this out. Now arguably that's an invalid optimization given the nature of decimal addition, but if you look at the generated code, you'll find the computation of
mymoney
doesn't involve an addition.I don't think I'd try to use adding 0.00m as a way to ensure a particular scale, to be honest. You could create your own code to enforce the scale, using
decimal.GetBits
and the constructor performing the reverse operation - but I don't think it would be terribly nice.Do you definitely need this "two decimal places" form as an intermediate value, or is it only for presentation? If it's the latter, I'd look at format strings instead.
作为 Jon 答案的补充,下面是从您的代码生成的 IL。正如他提到的,我的钱从未被添加。
要生成 IL(即,如果您将来想深入了解),只需从 VS 命令提示符运行 ILDASM,然后加载可执行文件并双击您想要查看的方法。
As an accompaniment to Jon's answer, below is the IL produced from your code. As he mentioned, mymoney was never added.
To produce the IL (i.e. if you want to look under the hood in the future), just run ILDASM from a VS command prompt, then load your executable and double-click on the method that you would like to look at.
因为 ConstPadding 为零!
你应该——
Because ConstPadding is zero!
You should -
具有常量填充的求和运算已完全从 MSIL 中排除,但它适用于非常量字段。
不幸的是,我无法找到对 FCallAddSub 函数的任何引用,但这是“优化”调用的函数。
The sum operation with the constant padding is getting completely excluded from the MSIL, yet it is there for a non-constant field.
I was not able to find any references to FCallAddSub function, unfortunately, but that's the one who "optimizes" the call.