2011-09-05 38 views
7

C# có các câu lệnh conditional operator và IF và tôi nghi ngờ rằng toán tử điều kiện sẽ chỉ là cú pháp. Vì vậy, tại thời gian biên dịch nó sẽ có một giống như một hoạt động IF.Tại sao sự khác biệt trong IL giữa IF và toán tử điều kiện?

Tuy nhiên họ không (xem bên dưới), họ có IL khác nhau. Cố gắng để quấn đầu của tôi xung quanh nó và giả định tôi có là đây là một tối ưu hóa hiệu suất mà các nhà điều hành có điều kiện được vì phạm vi hạn chế của nó.

Bạn có muốn biết giả định của tôi có đúng hay không và có thể nếu có nhiều hơn?

Cũng trong IF của IL có một số kiểm tra (L_000c, L_000d, L_000f) xung quanh giá trị int mà tôi không thể tìm ra ý nghĩa. Đây là những gì đã khiến tôi nghĩ rằng đây là một giải pháp mạnh mẽ hơn, với chi phí hiệu suất vì IF phạm vi lớn hơn.


Mã cho NẾU

var result = ""; 
if (Environment.Is64BitOperatingSystem) 
{ 
    result = "Yes"; 
} 
else 
{ 
    result = "No"; 
} 
Console.WriteLine(result); 

Mã cho nhà khai thác có điều kiện (Tôi nhận ra sự khác biệt, nhưng không có vấn đề làm thế nào tôi thay đổi nó - gán cho biến vv ... nó làm cho rất ít sự khác biệt)

Console.WriteLine("Is the OS x64? {0}", Environment.Is64BitOperatingSystem ? "Yes" : "No"); 

IL cho NẾU

L_0001: ldstr "" 
L_0006: stloc.0 
L_0007: call bool [mscorlib]System.Environment::get_Is64BitOperatingSystem() 
L_000c: ldc.i4.0 
L_000d: ceq 
L_000f: stloc.2 
L_0010: ldloc.2 
L_0011: brtrue.s L_001d 
L_0013: nop 
L_0014: ldstr "Yes" 
L_0019: stloc.0 
L_001a: nop 
L_001b: br.s L_0025 
L_001d: nop 
L_001e: ldstr "No" 
L_0023: stloc.0 
L_0024: nop 
L_0025: ldloc.0 
L_0026: call void [mscorlib]System.Console::WriteLine(string) 

IL f hoặc có điều kiện

L_002c: ldstr "Is the OS x64? {0}" 
L_0031: call bool [mscorlib]System.Environment::get_Is64BitOperatingSystem() 
L_0036: brtrue.s L_003f 
L_0038: ldstr "No" 
L_003d: br.s L_0044 
L_003f: ldstr "Yes" 
L_0044: call void [mscorlib]System.Console::WriteLine(string, object) 
+3

Chỉ cần chắc chắn: Bạn đang biên soạn trong chế độ Phát hành (NOP làm cho nó trông giống như Chế độ gỡ lỗi ngay từ cái nhìn đầu tiên)? Trong chế độ gỡ lỗi, trình biên dịch không thực hiện tất cả các tối ưu hóa để thực hiện gỡ lỗi dễ dàng hơn. –

+1

Chế độ gỡ lỗi hoặc phát hành này có phải không? 'Nop' xen kẽ được sử dụng cho các điểm phá vỡ, theo như tôi biết. –

+1

Cả hai đều ở chế độ phát hành? –

Trả lời

6

nếu

IL_0000: call  bool [mscorlib]System.Environment::get_Is64BitOperatingSystem() 
IL_0005: brfalse.s IL_000f 
IL_0007: ldstr  "Yes" 
IL_000c: stloc.0     // <------ Difference 1 
IL_000d: br.s  IL_0015 
IL_000f: ldstr  "No" 
IL_0014: stloc.0 
IL_0015: ldloc.0 
IL_0016: call  void [mscorlib]System.Console::WriteLine(string) 

? (toán tử ternary)

IL_001b: call  bool [mscorlib]System.Environment::get_Is64BitOperatingSystem() 
IL_0020: brtrue.s IL_0029 
IL_0022: ldstr  "No"   // <------ Difference 2 
IL_0027: br.s  IL_002e 
IL_0029: ldstr  "Yes" 
IL_002e: stloc.0 
IL_002f: ldloc.0 
IL_0030: call  void [mscorlib]System.Console::WriteLine(string) 

(gần) cùng mã cho cả trong chế độ phát hành. if thêm số stdloc.0 thứ hai không được trình biên dịch tối ưu hóa. Và sự khác biệt khác là truefalse bị đảo ngược.

(vì vậy tôi biết rằng tôi nên luôn luôn khởi động WinMerge!)

Và đây sẽ là một câu hỏi thú vị. Tại sao họ đảo ngược? Có logic nào không?

+0

Yip, được phát hiện tốt. Vấn đề là chế độ phát hành so với chế độ gỡ lỗi. –

+2

Bạn nói "sự khác biệt duy nhất", nhưng tất nhiên, trong '?'case,' 001b'-'0029' đang tính toán giá trị * của biểu thức điều kiện, và sau đó nó được gán cho một biến tại '002e', trong khi bên dưới câu lệnh if, có hai phép gán có thể (' 000c' và '0014'), tất nhiên có thể là các biến không liên quan và câu lệnh' if' không * có * một giá trị. –

+0

@Damien_The_Unbeliever Right. Đã sửa. Điều này dạy tôi rằng WinMerge là người bạn tốt nhất của lập trình viên :-) – xanatos

Các vấn đề liên quan