C#中"decimal"类型的有趣行为

ret*_*ide 20 c# decimal

如果我们将填充声明为const十进制,则填充不起作用.

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
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 15

编译器"知道"向值"添加零""不应该"更改值 - 因此它优化了这一点.现在可以说,鉴于十进制加法的性质,这是一个无效的优化,但如果你看一下生成的代码,你会发现计算mymoney不涉及添加.

老实说,我认为我不会尝试使用添加0.00米作为确保特定规模的方法.您可以创建自己的代码来强制执行扩展,使用decimal.GetBits构造函数执行反向操作 - 但我不认为它会非常好.

你肯定需要这个"两位小数"形式作为中间值,还是仅用于演示?如果是后者,我会查看格式字符串.

  • @Bueller:这就是我的答案的第一点 - 编译器正在删除添加,因为它知道它只添加0. (2认同)

Mic*_*odd 4

作为 Jon 答案的补充,下面是从您的代码生成的 IL。正如他提到的,我的钱从未被添加。

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       61 (0x3d)
  .maxstack  6
  .locals init ([0] valuetype [mscorlib]System.Decimal balance,
           [1] valuetype [mscorlib]System.Decimal padding,
           [2] valuetype [mscorlib]System.Decimal mymoney,
           [3] valuetype [mscorlib]System.Decimal yourmoney)
  IL_0000:  nop
  IL_0001:  ldc.i4.s   12
  IL_0003:  ldc.i4.0
  IL_0004:  ldc.i4.0
  IL_0005:  ldc.i4.0
  IL_0006:  ldc.i4.1
  IL_0007:  newobj     instance void [mscorlib]System.Decimal::.ctor(int32,
                                                                     int32,
                                                                     int32,
                                                                     bool,
                                                                     uint8)
  IL_000c:  stloc.0
  IL_000d:  ldc.i4.0
  IL_000e:  ldc.i4.0
  IL_000f:  ldc.i4.0
  IL_0010:  ldc.i4.0
  IL_0011:  ldc.i4.2
  IL_0012:  newobj     instance void [mscorlib]System.Decimal::.ctor(int32,
                                                                     int32,
                                                                     int32,
                                                                     bool,
                                                                     uint8)
  IL_0017:  stloc.1
  IL_0018:  ldloc.0
  IL_0019:  ldc.i4.2
  IL_001a:  call       valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::Round(valuetype [mscorlib]System.Decimal,
                                                                                          int32)
  IL_001f:  stloc.2
  IL_0020:  ldloc.0
  IL_0021:  ldloc.1
  IL_0022:  call       valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::op_Addition(valuetype [mscorlib]System.Decimal,
                                                                                                valuetype [mscorlib]System.Decimal)
  IL_0027:  ldc.i4.2
  IL_0028:  call       valuetype [mscorlib]System.Decimal [mscorlib]System.Decimal::Round(valuetype [mscorlib]System.Decimal,
                                                                                          int32)
  IL_002d:  stloc.3
  IL_002e:  ldloc.2
  IL_002f:  call       void [mscorlib]System.Console::WriteLine(valuetype [mscorlib]System.Decimal)
  IL_0034:  nop
  IL_0035:  ldloc.3
  IL_0036:  call       void [mscorlib]System.Console::WriteLine(valuetype [mscorlib]System.Decimal)
  IL_003b:  nop
  IL_003c:  ret
} // end of method Program::Main
Run Code Online (Sandbox Code Playgroud)

要生成 IL(即,如果您想在将来查看底层内容),只需从 VS 命令提示符运行 ILDASM,然后加载可执行文件并双击您想要查看的方法。