当前位置:  开发笔记 > 编程语言 > 正文

Is there a difference between "double val = 1;" and "double val = 1D;"?

如何解决《Isthereadifferencebetween"doubleval=1;"and"doubleval=1D;"?》经验,为你挑选了2个好方法。

Is there a difference between the following two pieces of code?

class Test {

    public readonly double Val;

    public Test(bool src) {
        this.Val = src ? 1 : 0;
    }

}

class Test {

    public readonly double Val;

    public Test(bool src) {
        this.Val = src ? 1D : 0D;
    }

}

I found that our code base uses the second way of writing.



1> Eric Lippert..:

这里有两个问题,需要注意的是,他们有不同的答案。

有没有之间的差异double val = 1;double val = 1D;

否。C#编译器可以识别在期望使用double的上下文中何时使用整数文字,并且在编译时进行类型更改,因此这两个片段将生成相同的代码。

以下两段代码之间有区别吗?

double Val; 
...    
this.Val = src ? 1 : 0;
---
this.Val = src ? 1D : 0D;

是。将整数常量自动更改为double的规则仅适用于常量,而src ? ...不是常量。就像您编写的那样,编译器将生成前者:

int t;
if (src)
  t = 1;
else
  t = 0;
this.Val = (double)t;

和第二个

double t;
if (src)
  t = 1D;
else
  t = 0D;
this.Val = t;

也就是说,在第一个中,我们选择一个整数,然后将其转换为双精度,在第二个中,我们选择一个双精度。

仅供参考:允许 C#编译器或抖动识别出可以将第一个程序优化为第二个程序,但是我不知道它是否确实可以这样做。C#编译器有时确实将用于提升算术的转换移到条件主体中。我大约在八年前就编写了该代码,但是我不记得所有的细节。



2> Matthew Wats..:

在生成的IL代码的差。

这节课:

class Test1
{
    public readonly double Val;

    public Test1(bool src)
    {
        this.Val = src ? 1 : 0;
    }
}

为构造函数生成以下IL代码:

.class private auto ansi beforefieldinit Demo.Test1
    extends [mscorlib]System.Object
{
    .field public initonly float64 Val

    .method public hidebysig specialname rtspecialname instance void .ctor (
            bool src
        ) cil managed 
    {
        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: ldarg.0
        IL_0007: ldarg.1
        IL_0008: brtrue.s IL_000d

        IL_000a: ldc.i4.0
        IL_000b: br.s IL_000e

        IL_000d: ldc.i4.1

        IL_000e: conv.r8
        IL_000f: stfld float64 Demo.Test1::Val
        IL_0014: ret
    }
}

和这个类:

class Test2
{
    public readonly double Val;

    public Test2(bool src)
    {
        this.Val = src ? 1d : 0d;
    }
}

为构造函数生成以下IL代码:

.class private auto ansi beforefieldinit Demo.Test2
    extends [mscorlib]System.Object
{
    .field public initonly float64 Val

    .method public hidebysig specialname rtspecialname instance void .ctor (
            bool src
        ) cil managed 
    {
        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: ldarg.0
        IL_0007: ldarg.1
        IL_0008: brtrue.s IL_0015

        IL_000a: ldc.r8 0.0
        IL_0013: br.s IL_001e

        IL_0015: ldc.r8 1

        IL_001e: stfld float64 Demo.Test2::Val
        IL_0023: ret
    }
}

如您所见,在第一个版本中,它必须调用conv.r8才能将int转换为double。

但是:(1)最终结果是相同的,并且(2)JIT编译器可以将它们都转换为相同的机器代码。

因此,答案是:是的,有一个区别-但不是一个,你需要操心。

就个人而言,我会选择第二个版本,因为它可以更好地表达程序员的意图,并且可能会产生效率更高的代码(取决于JIT编译器的工作方式)。

推荐阅读
ar_wen2402851455
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有