Có là một sự khác biệt trong các mã IL được tạo ra.
Lớp này:
class Test1
{
public readonly double Val;
public Test1(bool src)
{
this.Val = src ? 1 : 0;
}
}
Tạo mã IL này cho hàm tạo:
.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
}
}
Và lớp học này:
class Test2
{
public readonly double Val;
public Test2(bool src)
{
this.Val = src ? 1d : 0d;
}
}
Tạo mã IL này cho hàm tạo:
.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
}
}
Như bạn có thể thấy, trong phiên bản đầu tiên, nó phải gọi conv.r8để chuyển đổi một int thành gấp đôi.
Tuy nhiên: (1) Kết quả cuối cùng giống hệt nhau và (2) trình biên dịch JIT có thể dịch cả hai thứ này sang cùng một mã máy.
Vì vậy, câu trả lời là: Có, có là một sự khác biệt - nhưng không phải là một mà bạn cần phải lo lắng về.
Cá nhân, tôi sẽ dùng phiên bản thứ hai vì nó thể hiện rõ hơn ý định của lập trình viên và có thể tạo ra mã hiệu quả hơn một chút (tùy thuộc vào trình biên dịch JIT làm gì).