Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/297.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# “与”之间有区别吗;双val=1&引用;及;双val=1D&引用;?_C#_.net - Fatal编程技术网

C# “与”之间有区别吗;双val=1&引用;及;双val=1D&引用;?

C# “与”之间有区别吗;双val=1&引用;及;双val=1D&引用;?,c#,.net,C#,.net,以下两段代码之间有区别吗 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; } } 我

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

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;
    }

}

我发现我们的代码库使用了第二种编写方式。

没有区别,编译器足够聪明,可以隐式地进行转换,也可以不进行转换。
但是,如果使用
var
,则需要编写
var val=42D
以确保变量是double而不是int

double foo = 1;  // This is a double having the value 1
double bar = 1d; // This is a double having the value 1

var val = 42d;   // This is a double having the value 42
var val2 = 42;   // /!\ This is an int having the value 42 !! /!\
生成的IL代码中存在差异

这一类:

class Test1
{
    public readonly double Val;

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

    public Test2(bool src)
    {
        this.Val = src ? 1d : 0d;
    }
}
为构造函数生成此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 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
    }
}
这门课:

class Test1
{
    public readonly double Val;

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

    public Test2(bool src)
    {
        this.Val = src ? 1d : 0d;
    }
}
为构造函数生成此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 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编译器的使用情况)。

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

double val=1之间是否存在差异
double val=1D

不会。C#编译器会识别在预期使用双精度的上下文中何时使用整数文本,并在编译时更改类型,因此这两个片段将生成相同的代码

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

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;
    }

}
对。整数常量自动更改为双精度的规则仅适用于常量,
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;
也就是说,在第一种情况下,我们选择一个整数,然后将其转换为double,在第二种情况下,我们选择double


仅供参考:C#编译器或jitter可以识别第一个程序可以优化为第二个程序,但我不知道它是否真的这样做了。C#编译器有时会将提升算法的转换移动到条件语句体中;大约八年前我写过这段代码,但我记不起所有的细节。

在我的脑海里,第一段涉及到长时间到双倍的提升。第一段隐式转换为双倍,第二段不进行任何转换。你的问题标题和正文中的问题不匹配,这两个问题有不同的答案。@Eric Lippert事实上,问题的主体已经被其他用户编辑过。@Brian:不,原来的海报是正确的;编辑改变了问题的意思,我没有注意到。最初的问题是“有区别吗…?此外,有区别吗…?”,这是我的重点。删除的“进一步”表示原始海报意识到他们问了两个可能有不同答案的问题。这是一个坏习惯;问题最好只问一个问题。但是编辑使这两个问题看起来是同一个问题,而不是两个不同的问题。