V'è una differenza nel codice IL generato.
Questa classe:
class Test1
{
public readonly double Val;
public Test1(bool src)
{
this.Val = src ? 1 : 0;
}
}
Produce questo codice IL per il costruttore:
.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
}
}
E questa classe:
class Test2
{
public readonly double Val;
public Test2(bool src)
{
this.Val = src ? 1d : 0d;
}
}
Produce questo codice IL per il costruttore:
.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
}
}
Come puoi vedere, nella prima versione deve chiamare conv.r8per convertire un int in doppio.
Tuttavia: (1) Il risultato finale è identico e (2) il compilatore JIT potrebbe tradurre entrambi questi nello stesso codice macchina.
Quindi la risposta è: sì, c'è una differenza - ma non uno che avete bisogno di preoccuparsi.
Personalmente, sceglierei la seconda versione poiché esprime meglio l'intento del programmatore e potrebbe produrre un codice molto molto più efficiente (a seconda di cosa si occupa il compilatore JIT).