“Double val = 1;” arasında bir fark var mı? ve “çift val = 1D;”?


17

Aşağıdaki iki kod parçası arasında bir fark var mı?

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

}

Kod tabanımızın ikinci yazma yolunu kullandığını gördüm.


Başımın tepesinde, birincisi uzun ila iki kat promosyon içeriyor.
Tanveer Badar

2
ilk önce çifte örtülü dönüştürme yapar, ikincisi herhangi bir dönüştürme yapmaz.
Serkan Arslan

2
Soru başlığınız ve vücuttaki soru eşleşmiyor ve iki sorunun farklı cevapları var.
Eric Lippert

1
@Eric Lippert Aslında, sorunun gövdesi diğer kullanıcılar tarafından düzenlenmiştir.
srnldai

1
@Brian: Hayır, orijinal poster doğru; düzenleme, fark etmediğim sorunun anlamını değiştirdi. Asıl soru, "Bir fark var mı ...? Dahası, bir fark var mı ...?" Kaldırılan "İleri", orijinal posterin farklı cevapları olabilecek iki soru sorduğunu fark ettiğini gösterir . Bu kötü bir uygulama; sorular ideal olarak tek bir soru sormalıdır. Ancak düzenleme, iki sorunun aynı soru olması için tasarlandığını gösteriyor, iki farklı soru değil.
Eric Lippert

Yanıtlar:


18

Burada iki soru var ve farklı cevapları olduğunu belirtmek önemlidir.

Arasında bir fark var mı double val = 1;ve double val = 1D;?

Hayır. C # derleyicisi, bir tamsayı değişmezinin bir çiftin beklendiği bir bağlamda kullanıldığını algılar ve tür derleme zamanında değişir, böylece bu iki parça aynı kodu oluşturur.

Aşağıdaki iki kod parçası arasında bir fark var mı?

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

Evet. Tamsayı sabitleri otomatik çiftlerde değiştirilir bu kural için geçerlidir sabitler ve src ? ...bir değil sabit . Derleyici, yazdığınız gibi ilkini oluşturacaktır:

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

Ve ikincisi

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

Yani, ilkinde bir tamsayı seçer ve sonra onu ikiye dönüştürürüz ve ikincisinde bir çift seçeriz.

Bilginize: C # derleyicisi veya jitter , ilk programın ikinciye optimize edilebileceğini tanımasına izin verilir , ancak aslında bunu yapıp yapmadığını bilmiyorum. C # derleyicisi etmez bazen dönüşümlerini hareket kaldırdı Koşullamalar bedenlerine aritmetik; Bu kodu sekiz yıl önce yazdım, ama tüm detayları hatırlamıyorum.


6

Orada ise üretilen IL kodundaki bir fark vardır.

Bu sınıf:

class Test1
{
    public readonly double Val;

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

Yapıcı için bu IL kodunu üretir:

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

Ve bu sınıf:

class Test2
{
    public readonly double Val;

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

Yapıcı için bu IL kodunu üretir:

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

Gördüğünüz gibi, ilk versiyonda conv.r8int'i ikiye dönüştürmek için aramak zorunda.

Ancak: (1) Sonuç aynıdır ve (2) JIT derleyicisi her ikisini de aynı makine koduna iyi çevirebilir.

Cevaptır Yani: Evet, bir - ama hakkında endişe gerektiğini değil bir fark.

Şahsen, programcı niyeti daha iyi ifade ettiğinden ikinci versiyonu için gitmek istiyorum, ve olabilir (JIT derleyicisi kadar alır ne bağlı olarak) çok çok biraz daha verimli kod üretir.


4

Fark yok, derleyici bir dönüşümü dürüstçe yapabilecek veya yapamayacak kadar akıllı.
Ancak, kullanırsanız var, var val = 42D;değişkenin int değil, double olduğundan emin olmak için yazmanız gerekir .

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 !! /!\
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.