0

有时需要使用类型后缀(例如0d表示值为 0 的对偶或0f表示浮点数),并且通常被认为是好的样式。

但它有任何性能影响吗?

所以调用了几百万次

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

将尽可能快

if (x == 0) ...

我想,编译器会将 0 转换为 0.0 一次,因此性能无关紧要。但由于我在质量代码中看到过几次,我不确定......


由于注释而添加:x 不是 int,而是 double。

4

2 回答 2

4

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

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 中编译

一个重要的说法是在您确定这是一个瓶颈之前不要进行纳米优化。这样的优化通常会破坏代码的可读性和结果 - 可维护性。

于 2013-03-27T13:57:56.657 回答
0

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

Ilya 假设 x 是一个整数。如果是这种情况,他对转换 (conv.r8) 的评论是绝对正确的。但是我想到的情况是,如果您将 double 类型的变量与 double 文字进行比较。 在这种情况下,类型后缀有什么不同吗?

答案是不!

让我们看看这个小程序,比较 (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 代码:

.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 就好了......

于 2013-03-27T14:58:30.013 回答