在c#中使用类型后缀是否有任何性能提升?

本文关键字:任何 性能 是否 后缀 类型 | 更新日期: 2023-09-27 18:06:21

使用类型后缀(如0d对于值为0的双精度对象或0f对于float)有时是必要的,并且通常被认为是良好的风格。

但是它对性能有影响吗?

调用几百万次

if (x == 0d) ...   or
if (x == 0.0) ...

将和

一样快
if (x == 0) ...

我想,编译器会把0转换成0.0一次,所以这对性能没有影响。但自从我在高质量的代码中看到它几次后,我不确定…


由于注释而添加:x不是整型,而是双精度。

在c#中使用类型后缀是否有任何性能提升?

如果你检查IL代码,你会发现在比较int0.0文字时额外的conv操作码

int x = 0;
Console.WriteLine (x == 0.0);
IL_0000:  ldc.i4.0    
IL_0001:  stloc.0     // x
IL_0002:  ldloc.0     // x
IL_0003:  conv.r8     //<-- this is absent if literal is 0
IL_0004:  ldc.r8      00 00 00 00 00 00 00 00 
IL_000D:  ceq         
IL_000F:  call        System.Console.WriteLine

这是由于一个事实,Int32 ==操作符过载接受int作为第二个参数。

备注:使用上的编译器优化标志在LINQPad中编译。

一个重要的备注不要做纳米级优化,直到你确定这是一个瓶颈。这样的优化通常会破坏代码的可读性和可维护性。

根据Ilya Ivanov的提示,我检查了一个小示例程序的IL代码。

Ilya假设x是一个整数。如果是这样的话,他关于转换的评论是绝对正确的(conv.r8)。但是我想到的情况是,如果你比较一个double类型的变量和一个double字面量。类型后缀在这种情况下有任何区别吗?

答案是:NO!

让我们看一下这个小程序,比较(d == 0)或(d == 0d):

static void Main(string[] args)
{
    double d = 0.0;
    if (d == 0)     // if (d == 0d)
        d = 1.23;
    Console.WriteLine(d);
}

两个版本编译成完全相同的IL-Code:

.method private hidebysig static 
    void Main (
        string[] args
    ) cil managed 
{
    // Method begins at RVA 0x2050
    // Code size 48 (0x30)
    .maxstack 2
    .entrypoint
    .locals init (
        [0] float64 d,
        [1] bool CS$4$0000
    )
    IL_0000: nop
    IL_0001: ldc.r8 0.0
    IL_000a: stloc.0
    IL_000b: ldloc.0
    IL_000c: ldc.r8 0.0
    IL_0015: ceq
    IL_0017: ldc.i4.0
    IL_0018: ceq
    IL_001a: stloc.1
    IL_001b: ldloc.1
    IL_001c: brtrue.s IL_0028
    IL_001e: ldc.r8 1.23
    IL_0027: stloc.0
    IL_0028: ldloc.0
    IL_0029: call void [mscorlib]System.Console::WriteLine(float64)
    IL_002e: nop
    IL_002f: ret
} // end of method Program::Main

当然汇编代码也是一样的

所以写0而不是0.0或0d就可以了