2010-05-07 58 views
12

Tôi đang cố đọc mã C# đã biên soạn của mình.C#, tối ưu hóa lạ

đây là mã của tôi:

using(OleDbCommand insertCommand = new OleDbCommand("...", connection)) 
{ 
    // do super stuff 
} 

Nhưng!

Chúng ta đều biết rằng một sử dụng được dịch như sau:

{ 
    OleDbCommand insertCommand = new OleDbCommand("...", connection) 
    try 
    { 
     //do super stuff 
    } 
    finally 
    { 
     if(insertCommand != null) 
      ((IDisposable)insertCommand).Dispose(); 
    } 
} 

(kể từ OleDbCommand là một loại tài liệu tham khảo).

Nhưng khi tôi biên soạn lại lắp ráp của tôi (biên soạn với .NET 2.0) tôi có được điều này trong Resharper:

try 
{ 
    insertCommand = new OleDbCommand("", connection); 
Label_0017: 
    try 
    { 
     //do super stuff 
    } 
    finally 
    { 
    Label_0111: 
     if ((insertCommand == null) != null) 
     { 
      goto Label_0122; 
     } 
     insertCommand.Dispose(); 
    Label_0122:; 
    } 

Tôi đang nói về dòng này: if ((insertCommand == null) != null).

Giả sử insertCommand IS null. Sau đó, phần đầu tiên trả về true. (true != null) trả về true. Vậy thì việc xử lý vẫn bị bỏ qua? Lạ thật, rất lạ.

Nếu tôi dán điều này trong Visual Studio, Resharper đã cảnh báo tôi: Biểu thức luôn đúng ...

Cảm ơn!

-Kristof

+0

Tôi đã đọc câu hỏi của bạn đúng cách, tôi đoán rằng có lỗi trong Resharper, tôi khuyên bạn nên thử một số trình giải mã khác và xem kết quả bạn nhận được. –

+1

Bạn sử dụng công cụ nào để dịch ngược? Có lẽ bạn nên thử một số khác –

Trả lời

12

Các decompiler có một lỗi. Dòng này

if ((insertCommand == null) != null) 

nên đã được dịch ngược để

if ((insertCommand == null) != false) 

đó, mặc dù không cần thiết tiết, ít nhất là đúng mã.

Các decompiler lẽ làm phiên bản không cần thiết tiết này vì # biên dịch C thường chọn để phát ra

if (x) 
    Y(); 
Z(); 

như nếu bạn đã viết

if (!x) 
    goto L; 
Y(); 
L: Z(); 

Kể từ khi mã được tạo cho cả hai chương trình là như nhau , trình giải mã không phải lúc nào cũng biết mã nào là mã hợp lý hơn để hiển thị.

Lý do cho sự bất ngờ "!= false "là khi chúng ta tạo ra IL để kiểm tra xem có điều gì là đúng hay không, thì mã nhanh nhất và nhỏ nhất mà chúng ta có thể tạo ra là kiểm tra xem nó có phải là false hay không. Điều này có nghĩa là không? "

+0

Có hợp pháp để gọi đây là một lỗi trong trình dịch ngược không? Có thể người dùng đã viết cod e trông giống như trường hợp thứ 2, do đó trình biên dịch không có cách nào thực sự để biết cái nào cần chọn. Hoặc là bạn đề xuất trình biên dịch nên ưu tiên tránh gotos trong loại tình huống này vì hầu hết người dùng không sử dụng chúng. – Brian

+1

@Brian: Trình biên dịch không có cách nào tránh gotos; * một câu lệnh if là một goto *. Một câu lệnh if chỉ là một cách dễ chịu để viết một goto có điều kiện; đừng lừa mình nghĩ rằng nó là bất cứ điều gì khác hơn thế. Điều đó nói rằng, một heuristic tốt cho một decompiler là để dịch ngược mã mà người dùng nhiều khả năng đã viết khi nó là mơ hồ. Lỗi là sự giải mã của một so sánh của một số nguyên bằng không được tạo ra như là một so sánh với null, mà không phải là hợp pháp C#. Nó sẽ được tạo ra như là một so sánh với sai. –

+0

Xin lỗi, tôi có nghĩa là để nói hỏi nếu bạn đã đề xuất trình biên dịch * de * nên ưu tiên tránh gotos. Đó không phải là vấn đề, như bạn chỉ ra. – Brian

0

khi bạn dịch ngược mã, bạn không được bảo đảm lấy lại mã gốc. Khi mã .net được biên dịch sang IL, nó được tối ưu hóa. Đôi khi bạn sẽ thấy một số điên khi một ứng dụng dịch IL trở lại vào C#. Điều này không có nghĩa là mã không hoạt động, nó chỉ là cách ứng dụng (resharper trong trường hợp này) đã dịch IL.

Nếu bạn lo lắng về điều đó, tôi sẽ xem trực tiếp tại IL để xem nội dung được biên soạn.

Lưu ý phụ: IL bị biên dịch thành C# hoặc VB.net không được đảm bảo để biên dịch. :)

sản phẩm khác để thử là Reflector

+0

Tôi đã sử dụng Reflector :) – Snake

+0

Trình phản chiếu chắc chắn chứa nhiều lỗi. Tôi đã báo cáo một lỗi và không bao giờ nhận được trả lời ngay cả http: //www.red-gate .com/MessageBoard/viewtopic.php? t = 8858 –