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:不,原来的海报是正确的;编辑改变了问题的意思,我没有注意到。最初的问题是“有区别吗…?此外,有区别吗…?”,这是我的重点。删除的“进一步”表示原始海报意识到他们问了两个可能有不同答案的问题。这是一个坏习惯;问题最好只问一个问题。但是编辑使这两个问题看起来是同一个问题,而不是两个不同的问题。