Não é uma diferença no código IL gerado.
Esta aula:
class Test1
{
public readonly double Val;
public Test1(bool src)
{
this.Val = src ? 1 : 0;
}
}
Produz este código IL para o construtor:
.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 esta classe:
class Test2
{
public readonly double Val;
public Test2(bool src)
{
this.Val = src ? 1d : 0d;
}
}
Produz este código IL para o construtor:
.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
}
}
Como você pode ver, na primeira versão, é necessário chamar conv.r8para converter um int em um duplo.
No entanto: (1) o resultado final é idêntico e (2) o compilador JIT pode muito bem converter esses dois no mesmo código de máquina.
Portanto, a resposta é: Sim, há é uma diferença - mas não aquele que você precisa para se preocupar.
Pessoalmente, eu optaria pela segunda versão, pois ela expressa melhor a intenção do programador e pode produzir código muito ligeiramente mais eficiente (dependendo do que o compilador JIT aprende).