Các vô điều hành liên hiệp là rõ ràng hơn nhiều khi kiểm tra null, đó là mục đích chính của nó. Nó cũng có thể bị xiềng xích.
object a = null;
object b = null;
object c = new object();
object d = a ?? b ?? c; //d == c.
Trong khi điều hành được giới hạn để null kiểm tra, các nhà điều hành ternary là không. Ví dụ
bool isQuestion = true;
string question = isQuestion ? "Yes" : "No";
tôi nghĩ mọi người chỉ không nhận thức của người điều khiển vô liên hiệp để họ sử dụng các nhà điều hành ternary để thay thế. ternary tồn tại trước C# trong hầu hết các ngôn ngữ phong cách C vì vậy nếu bạn không biết C# bên trong và ra ngoài và/hoặc bạn lập trình bằng ngôn ngữ khác, te rnary là một sự lựa chọn tự nhiên. Nếu bạn đang kiểm tra null mặc dù, sử dụng toán tử kết hợp null, nó được thiết kế cho điều đó, và IL được tối ưu hóa một chút (so sánh với một if nếu khác).
Dưới đây là một ví dụ so sánh việc sử dụng của mỗi
object a = null;
object b = null;
object c = null;
object nullCoalesce = a ?? b ?? c;
object ternary = a != null ? a : b != null ? b : c;
object ifThenElse;
if (a != null)
ifThenElse = a;
else if (b != null)
ifThenElse = b;
else if (c != null)
ifThenElse = c;
Thứ nhất, chỉ cần nhìn vào cú pháp for null liên hiệp, đó là cách rõ ràng hơn. Ternary thực sự khó hiểu. Bây giờ cho phép nhìn vào IL
Null liên hiệp Chỉ
.entrypoint
.maxstack 2
.locals init (
[0] object a,
[1] object b,
[2] object c,
[3] object nullCoalesce)
L_0000: ldnull
L_0001: stloc.0
L_0002: ldnull
L_0003: stloc.1
L_0004: newobj instance void [mscorlib]System.Object::.ctor()
L_0009: stloc.2
L_000a: ldloc.0
L_000b: dup
L_000c: brtrue.s L_0015
L_000e: pop
L_000f: ldloc.1
L_0010: dup
L_0011: brtrue.s L_0015
L_0013: pop
L_0014: ldloc.2
L_0015: stloc.3
L_0016: ldloc.3
L_0017: call void [mscorlib]System.Console::WriteLine(object)
L_001c: ret
ternary Chỉ
.entrypoint
.maxstack 2
.locals init (
[0] object a,
[1] object b,
[2] object c,
[3] object ternary)
L_0000: ldnull
L_0001: stloc.0
L_0002: ldnull
L_0003: stloc.1
L_0004: newobj instance void [mscorlib]System.Object::.ctor()
L_0009: stloc.2
L_000a: ldloc.0
L_000b: brtrue.s L_0016
L_000d: ldloc.1
L_000e: brtrue.s L_0013
L_0010: ldloc.2
L_0011: br.s L_0017
L_0013: ldloc.1
L_0014: br.s L_0017
L_0016: ldloc.0
L_0017: stloc.3
L_0018: ldloc.3
L_0019: call void [mscorlib]System.Console::WriteLine(object)
L_001e: ret
Nếu Rồi Else Chỉ
.entrypoint
.maxstack 1
.locals init (
[0] object a,
[1] object b,
[2] object c,
[3] object ifThenElse)
L_0000: ldnull
L_0001: stloc.0
L_0002: ldnull
L_0003: stloc.1
L_0004: newobj instance void [mscorlib]System.Object::.ctor()
L_0009: stloc.2
L_000a: ldloc.0
L_000b: brfalse.s L_0011
L_000d: ldloc.0
L_000e: stloc.3
L_000f: br.s L_001a
L_0011: ldloc.1
L_0012: brfalse.s L_0018
L_0014: ldloc.1
L_0015: stloc.3
L_0016: br.s L_001a
L_0018: ldloc.2
L_0019: stloc.3
L_001a: ldloc.3
L_001b: call void [mscorlib]System.Console::WriteLine(object)
L_0020: ret
IL không phải là một trong những điểm mạnh của tôi, vì vậy có thể ai đó có thể chỉnh sửa câu trả lời của tôi và mở rộng câu trả lời trên đó. Tôi sẽ giải thích lý thuyết của tôi, nhưng tôi không muốn nhầm lẫn bản thân mình và những người khác. Số LOC tương tự cho cả ba, nhưng không phải tất cả các toán tử IL đều có cùng thời gian thực thi.
Một lý do là ppl có thể không được nhận biết! – vpram86
phải là "var res = (dữ liệu! = Null)? Dữ liệu: dữ liệu mới();" trong mẫu của bạn –
@Rubens, chỉ ngớ ngẩn và không đúng. – kenny