2010-05-27 35 views
13

Tôi vừa xem đoạn mã này trong một số mã Exchange 2010 và tôi đã tự hỏi liệu có ai biết tại sao lập trình viên đã thực hiện theo cách này hay không. Tôi chưa bao giờ thấy một câu lệnh If được định dạng như thế này. Nó có vẻ như vậy ngược lại phải có một lý do chính đáng cho nó ??C# if statement. hoạt động bên trong Q

if (true == MsgItem.HasAttachments) 
{ 
    // Code 
} 

Tôi cho rằng nó có thể có một số tối ưu hóa theo nhiều cách khác nhau để mã hóa cùng một thứ;

if (MsgItem.HasAttachments) 
{ 
    // Code 
} 

hoặc

if (MsgItem.HasAttachments == true) 
{ 
    // Code 
} 

của nó không phải là một vấn đề lớn tôi chỉ tò mò.

Cảm ơn, Mike

UPDATE: Cảm ơn tất cả những điểm thú vị nâng lên. Tóm tắt có vẻ là nó xuống đến các tiêu chuẩn mã hóa kế thừa.

+1

Thói quen của lập trình viên? –

+0

có thể trùng lặp của [== Toán tử và toán hạng] (http://stackoverflow.com/questions/677264/operator-and-operands) – ChrisF

+4

"phải có lý do chính đáng cho nó" == false –

Trả lời

31

Đó là một thói quen còn sót lại từ C hoặc C++, nơi bạn có thể vô tình làm:

if (i = 1) { 
} 

này vô tình gán 1-i thay vì làm một so sánh.

Đảo ngược thứ tự trong séc ngăn ngừa sai lầm phổ biến này.

if (1 = i) { 
} 

Điều đó sẽ không biên dịch, và nó rất dễ dàng để thấy rằng bạn nhầm gõ = thay vì ==.

Điều này vẫn có liên quan cho bools trong C# vì giá trị của bài tập là giá trị được gán.

Therefor:

if (SomeBoolVar = true) { 
} 

Sẽ luôn luôn là sự thật bởi vì bạn đang lưu trữ true vào SomeBoolVar mà đánh giá để true. Một sai lầm nhỏ có thể khó theo dõi.

+14

Những người sử dụng 'if (SomeBoolVar = true)' thay vì 'if (SomeBoolVar)' nên cắt tay :-) – paxdiablo

+1

Haha, hoặc ít nhất là ngón tay cái của họ, để thanh không gian là một cơn đau ở mông sử dụng. (@paxdia) – jjnguy

+3

Trình biên dịch C# của Microsoft cũng sẽ đưa ra một cảnh báo nếu bạn vô tình sử dụng '=' thay vì '==' trong một biểu thức có điều kiện. – LukeH

11

Đây được gọi là "Yoda Conditions" - ý tưởng ban đầu là nếu bạn vô tình nhập một =, quá trình biên dịch sẽ thất bại vì giá trị không đổi nằm ở phía bên tay trái.

14

lập trình C++ và C đôi khi đưa hằng số đầu tiên, để tránh vô tình viết

if (variable = constant) 

mà sẽ thực hiện một bài tập.

Đặc biệt, một cách rõ ràng để so sánh boolean, giả sử HasAttachments là ghi, tuyên bố này sẽ biên dịch và chạy không có cảnh báo , nhưng không có hành vi dự định trong C#:

if (MsgItem.HasAttachments = true) 

Đối với các biểu thức không Boolean, đây không phải là vấn đề trong C# vì điều kiện của câu lệnh if phải được chuyển đổi hoàn toàn thành bool ... và đối với biểu thức Boolean, biểu mẫu ở giữa của bạn được ưu tiên:

if (MsgItem.HasAttachments) 

Tôi sẽ ngạc nhiên nếu nó có bất kỳ tác động hiệu suất nào - và có lẽ không ảnh hưởng đến IL được tạo ra để bắt đầu.


Rất tiếc - # biên dịch MS C không thực sự cảnh báo cho việc này:

cảnh báo CS0665: Chuyển nhượng trong biểu thức điều kiện luôn luôn là hằng số; bạn có ý định sử dụng == thay vì =?

Tôi chưa thử qua Mono; có thể hoặc không thể đưa ra cảnh báo. Chắc chắn là hợp lệ mã C#.

+0

Tin hay không, nó dịch sang * hơi * khác nhau IL. Xem câu trả lời của jeffmaphone cho [một câu hỏi rất giống tôi đã đăng một thời gian dài trước đây] (http://stackoverflow.com/questions/1070063/does-if-bool-true-require-one-more-step-than-if-bool). –

+0

@Dan: câu trả lời của jeffmaphone đang sử dụng C++ chứ không phải C#. Trong C# chúng sẽ biên dịch chính xác cùng một IL. – LukeH

+0

@ LukeH: Ha, cảm ơn đã nhắc nhở tôi (nên đọc lại câu trả lời trước khi liên kết với nó - bỏ qua để nhận ra câu hỏi này là C# -specific trong khi tôi là ngôn ngữ bất khả tri). Và tôi nhận thấy bạn là người đã chỉ ra thực tế này trong câu hỏi đã nói! –

1

có thể nhà điều hành == đã bị quá tải và MsgItem.HasAttachments có thêm thông tin sau đó chỉ cần bool? Tôi không biết. Chỉ là một ý tưởng.

+1

Ah cũ "Hàng ngày WTF" {đúng, sai, có thể} loại :-) – paxdiablo

+1

Không, nếu bạn quá tải nhà điều hành bình đẳng những điều không phải lúc nào họ có vẻ. Nếu bạn có 'true == MsgItem.HasAttachments', nó sẽ chạy toán tử == cho lớp bool và truyền MsgItem.HasAttachments vào thực thi toán tử. Nếu bạn có nó theo cách khác, nó sẽ chạy toán tử == implemantation trên kiểu HasAttachments và truyền 'true' vào nó. Rõ ràng hành vi không nhất thiết phải giống nhau. Vì vậy, ít nhất là khi các toán tử quá tải, thứ tự thường tạo ra sự khác biệt. – Cobusve

0

Đây là yêu cầu chung khi viết mã quan trọng. Nó ở đó để ngăn chặn việc giao ngẫu nhiên khi bạn định làm séc. Trong một ngôn ngữ như C# trình biên dịch sẽ cảnh báo bạn về nó, vì vậy nó không phải là cần thiết, nhưng nó là một thói quen còn lại cho nhiều lập trình viên.

6

Bởi vì các lập trình viên là một chú hề :-) Toàn bộ các điểm điều kiện boolean là bạn đặt tên cho chúng như vậy mà họ làm cảm giác như boolean:

if (MsgItem.HasAttachments) 

và điều này rõ ràng làm như vậy tôi không biết lý do tại sao người lập trình tự bắn vào chân bằng cách kiểm tra sự bình đẳng chống lại true.

Bởi vì, trong mọi mức độ nghiêm trọng, true == MsgItem.HasAttachments chỉ là một số khác là boolean, vậy bạn sẽ dừng ở đâu?

if (true == MsgItem.HasAttachments) 
if (true == (true == MsgItem.HasAttachments)) 
if (true == (true == (true == MsgItem.HasAttachments))) 
: : : 

Và cứ thế, quảng cáo vô cùng.

Toàn bộ lừa của việc sử dụng hằng số đầu tiên để tránh những vấn đề vô tình sử dụng = phân công thay vì == bình đẳng không phải là một vấn đề ở đây kể từ khi bạn không nên kiểm tra một boolean chống lại một trong hai true hoặc false.Bạn nên sử dụng một trong số:

if (cond) 
if (!cond) 
2

Dưới mono, tất cả họ đều tạo ra cùng IL (ldloc.0; brfalse <LOC>):

Nguồn:

using System; 
class Foo 
{ 
    static void Main() 
    { 
     bool bar = Console.ReadLine() == "bar"; 
     if (bar) 
     { 
      Console.WriteLine("bar"); 
     } 

     if (true == bar) 
     { 
      Console.WriteLine("true == bar"); 
     } 

     if (bar == true) 
     { 
      Console.WriteLine("bar == true"); 
     } 
    } 
} 

IL:

// snip... 
IL_000a: call bool string::op_Equality(string, string) 
IL_000f: stloc.0 
IL_0010: ldloc.0 
IL_0011: brfalse IL_0020 

IL_0016: ldstr "bar" 
IL_001b: call void class [mscorlib]System.Console::WriteLine(string) 
IL_0020: ldloc.0 
IL_0021: brfalse IL_0030 

IL_0026: ldstr "true == bar" 
IL_002b: call void class [mscorlib]System.Console::WriteLine(string) 
IL_0030: ldloc.0 
IL_0031: brfalse IL_0040 
// snip... 

Cá nhân, điều đó khiến tôi phát điên khi mọi người làm if (SomePredicate() == true). Trừ khi nó thực sự trở về một đối tượng với một toán tử quá tải ==, việc so sánh với true là hoàn toàn không cần thiết. Tại sao dừng lại ở một so sánh?

// make extra sure SomePredicate returns true 
if ((SomePredicate() == true) == true) 
{ 
    // ... 
} 
3

Có một lý do hoàn toàn tốt đẹp để viết if (true == myvar): biến (hoặc biểu hiện) có thể không là một biểu thức boolean - nó có thể là một bool?. Biểu thức sau đó sẽ tương đương với if(myvar ?? false) - và tôi thích cú pháp thứ hai này vì nó ngay lập tức hiển nhiên rằng bạn đang xử lý một giá trị nullable. Về mặt kỹ thuật, một nhà điều hành == tùy chỉnh đang được sử dụng (có khả năng kết hợp với chuyển đổi loại tiềm ẩn), nhưng điều đó không chắc khi thực hiện một cái gì đó như thế thường bị cau mày và không thực tế hoặc tiện dụng.

Đặt hằng số trước, như nhiều thứ khác đã chỉ ra, có thể làm giảm các lỗi ngẫu nhiên - cá nhân, tôi không nghĩ rằng những lỗi đó thường xảy ra thường xuyên, nhưng không thể gây hại.

Rất có thể, tuy nhiên, tác giả ban đầu chỉ hơi bối rối khi ông viết mã đó.

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