Tại sao nên sử dụng! Boolean_variable Over boolean_variable == false


59

Một nhận xét về câu hỏi này: Kiểm tra nếu một phương thức trả về false: gán kết quả cho biến tạm thời, hoặc đặt lời gọi phương thức trực tiếp trong điều kiện? nói rằng bạn nên sử dụng !booleanthay vì boolean == falsekhi kiểm tra điều kiện. Tại sao? Đối với tôi boolean == falselà tiếng Anh tự nhiên hơn nhiều và rõ ràng hơn. Tôi xin lỗi nếu đây chỉ là một vấn đề về phong cách, nhưng tôi đã tự hỏi nếu có một số lý do khác cho sở thích này !boolean?


28
Nó ngắn hơn để viết.
Zenon

39
Nó giống như làm boolean == true: nó không có ý nghĩa. Biểu thức bên trong các ifcâu lệnh chỉ là: biểu thức. Nếu một cái gì đó đã được đánh giá thành một biểu thức boolean, tại sao bạn lại thêm một kiểm tra để buộc nó phải đánh giá nó?
Tối đa

10
@zzzzBov: Ừm, không. Đó không phải là cách mà hầu hết các lập trình viên (kiểu C) làm điều đó.
amara

9
@zzzzBov: Nhận xét của bạn không rõ ràng. Nếu bạn muốn nói đó !boolean_variablelà cách mà hầu hết các lập trình viên C làm điều đó, tôi đồng ý.
Keith Thompson

29
Và quan trọng hơn, tại sao không ai muốn viết boolean != true?

Câu trả lời:


153

Khi tôi thấy một dòng như thế if (!lateForMeeting()), tôi đọc nó là "Nếu không trễ cuộc họp" , điều này khá dễ hiểu, trái ngược với if (lateForMeeting() == false)điều tôi đã đọc là "Nếu thực tế là tôi đến trễ cuộc họp là sai " .

Chúng giống nhau về nghĩa, nhưng trước đây gần giống với cách xây dựng câu tiếng Anh tương đương.


27
+1 Trong Python bạn thực sự viết if not late_for_meeting:)
phunehehe

42
Tôi cho rằng nếu "nếu ___ là sai" nghe có vẻ tự nhiên hơn "nếu không ___", thì tên của ___ cần được cải thiện.
Mike DeSimone

12
Trong Perl bạn có thể viếtunless late_for_meeting
Henrik Ripa

4
@HenrikRipa: Có vẻ như bất cứ thứ gì bạn có thể nhập là mã hợp pháp trong Perl. Có hay không nó làm những gì bạn muốn là một câu hỏi khác;)
Adam Robinson

4
@ A-Cube Tôi sẽ không có một phương pháp như thế để bắt đầu. Thay vào đó, tôi có một phương thức gọi là done(). Tiêu cực kép là xấu.
kba

97

Viết == false== truelà dư thừa. Nó có thể được đưa đến thái cực tùy ý, quá. Nếu bạn bắt đầu viết

if (condition == false) { ... }

Vậy thì tại sao không

if ((condition == false) == true) { ... }

Hay tại sao không

if ((someExp == anotherExp) == true) { ... }

Đạo đức của câu chuyện này là nếu conditionlà một biểu thức boolean, thì bạn không cần phải thêm == false; đó là những gì nhà điều hành !dành cho;)


Đừng nghĩ về điều này!
ell

51
== falseKHÔNG dư thừa, chỉ dài dòng hơn !. OTOH, == truelà dư thừa.
dan04

4
@ dan04 Bạn nói đúng. Tuy nhiên, theo nghĩa của tôi, nó vẫn là một ý tưởng tồi. Xem xét (exp1 != exp2)so với ((exp1 == exp2) == false). Phải thừa nhận rằng đây là những tình huống có thể xảy ra, nhưng bạn hầu như không bao giờ nên viết những so sánh rõ ràng thành đúng hay sai. Cũng như bạn nên sử dụng toán tử !=, vì vậy bạn nên sử dụng !.
Andres F.

26
@ dan04: Nó là dư thừa khi ngôn ngữ đã cung cấp !.
DeadMG

5
@ dan04: Bất cứ khi nào bạn viết bool_expression == bool_literal, == ...là dư thừa. Cho dù bạn đang kiểm tra đúng hay sai đều không liên quan. Nó chỉ là một sự thay đổi theo thứ tự của các khối kết quả / thay thế. Các ví dụ của Andres minh họa điểm này một cách hoàn hảo. Hầu hết các trình biên dịch hiện đại sẽ tối ưu hóa sự dư thừa, nhưng nó vẫn dư thừa.
Lèse majesté

70

Trong C và một số ngôn ngữ tương tự, so sánh các biểu thức boolean cho bằng falsehoặc truelà một thói quen nguy hiểm.

Trong C, bất kỳ biểu thức vô hướng (số hoặc con trỏ) có thể được sử dụng trong ngữ cảnh boolean, ví dụ như điều kiện của một ifcâu lệnh. Quy tắc C if (cond)tương đương với if (cond != 0)- tức là 0 là sai và mọi giá trị khác không là đúng. Nếu condthuộc loại con trỏ, 0được coi là hằng số con trỏ null; if (ptr)có nghĩa là if (ptr != NULL).

Điều này có nghĩa rằng

if (cond)

if (cond == true)

không có nghĩa là điều tương tự . Điều đầu tiên là đúng nếu condkhác không; điều thứ hai chỉ đúng nếu nó bằng true, mà trong C (nếu bạn có #include <stdbool.h>) chỉ đơn giản là 1.

Ví dụ, isdigit()hàm được khai báo <ctype.h>trả về một intgiá trị, 0nếu đối số là một chữ số, khác không nếu không. Nó có thể trở lại 42để chỉ ra rằng điều kiện là đúng. So sánh 42 == truesẽ thất bại.

Nó xảy ra 0là giá trị duy nhất được coi là sai, vì vậy so sánh cho sự bình đẳng falsesẽ hoạt động; if (!cond)if (cond == false)làm điều tương tự. Nhưng nếu bạn sẽ tận dụng lợi thế đó, bạn phải nhớ rằng so sánh với falselà ổn, và so sánh với truethì không. Tệ hơn nữa, so sánh với truesẽ hoạt động hầu hết thời gian (ví dụ, các toán tử đẳng thức và quan hệ luôn mang lại một trong hai 0hoặc 1). Điều này có nghĩa là bất kỳ lỗi nào bạn giới thiệu bằng cách sử dụng điều này vẫn có thể khó theo dõi. (Đừng lo lắng, họ sẽ xuất hiện ngay khi bạn giới thiệu mã cho một khách hàng quan trọng.)

C ++ có các quy tắc hơi khác nhau; ví dụ, boolloại của nó được tích hợp chặt chẽ hơn một chút vào ngôn ngữ và if (cond)chuyển đổi condthành loại bool. Nhưng hiệu quả là (hầu hết) như nhau.

Một số ngôn ngữ khác có những gì người ta có thể gọi là booleans có hành vi tốt hơn, như vậy cond == truecond == false(hoặc bất cứ cú pháp nào xảy ra) đều an toàn. Mặc dù vậy, tất cả các ngôn ngữ tôi đã nhìn thấy có một nothoặc !điều hành; Nó ở đó, vì vậy bạn cũng có thể sử dụng nó. Sử dụng cond == falsechứ không phải !condhoặc not condkhông, theo tôi, cải thiện khả năng đọc. (Đúng là !nhân vật có thể khó nhìn thấy trong nháy mắt; đôi khi tôi thêm một khoảng trắng sau !để tránh điều này.)

Và thường thì bạn có thể tránh được vấn đề cải thiện sự rõ ràng bằng cách sắp xếp lại mã một chút. Ví dụ: thay vì:

if (!cond) {
    do_this();
}
else {
    do_that();
}

bạn có thể viết:

if (cond) {
     do_that();
}
else {
    do_this();
}

Điều đó không phải lúc nào cũng tốt hơn, nhưng sẽ không hại gì khi tìm kiếm cơ hội.

Tóm tắt: Trong C và C ++, so sánh bình đẳng truefalsenguy hiểm, quá dài dòng và phong cách kém. Trong nhiều ngôn ngữ khác, những so sánh như vậy có thể không nguy hiểm, nhưng chúng vẫn quá dài dòng và phong cách kém.


+1 cho điều này là một câu trả lời với lời giải thích kỹ thuật hữu ích thực tế.
Mike Nakis

Tôi vẫn nghĩ theo cách này, bất kể ngôn ngữ lập trình tôi luôn cho rằng điều đó == truekhông an toàn. Cảm thấy tốt hơn theo cách đó.
Dervall

1
@Dervall: giả sử một cái gì đó đơn giản không phải là trường hợp cũng không tốt. Có một vài trường hợp góc trong một số ngôn ngữ nhất định trong đó so sánh bình đẳng của booleans không chỉ an toàn mà trên thực tế là phù hợp, ví dụ như trong Haskell, có một hệ thống loại không có tiềm năng mạnh mẽ với suy luận hai chiều, người ta có thể viết (==True) . fđể làm rõ điều đó chúng tôi muốn -> Boolkhởi tạo hàm trả về đa hình f. Điều đó rõ ràng hơn not . not . fvà ít khó xử hơn (f :: a -> Bool).
rẽ trái

Ngoài ra, nó chắc chắn thích hợp để làm những thứ như pred(x)==pred(y)cho hàm bool-return pred. Sự thay thế sẽ là pred(x)? pred(y) : !pred(y)điều mà bạn sẽ đồng ý là khó chấp nhận.
rẽ trái

1
@leftaroundabout: Điều đó tốt nếu bạn biết điều đó pred(x)pred(y)sử dụng cùng một giá trị để biểu thị sự thật, đó là một giả định an toàn trong một số ngôn ngữ nhưng không phải trong các ngôn ngữ khác. Trong C, ví dụ, bạn có thể viết !!pred(x) == !!pred(y).
Keith Thompson

13

Nếu condition == falsethực sự là tiếng Anh tự nhiên hơn nhiều trong tiếng Anh đối với bạn thì tôi phải cho rằng bạn không phải là người bản ngữ. Nếu không, tôi không thể giải thích điều này, bởi vì không ai nói như thế:

Nếu mặt trời chiếu sáng là sai tôi ở nhà.

So sánh với

Nếu mặt trời không chiếu sáng tôi ở nhà.

Điều đó nói rằng, tôi đồng ý rằng !nhân vật đơn lẻ, mảnh khảnh dễ bị bỏ qua trong mã. Vì lý do đó, tôi thích từ khóa notkhi được hỗ trợ bởi ngôn ngữ. C ++ ví dụ không cho phép điều này mặc dù nhiều lập trình viên không nhận thức được nó.

Đối với các ngôn ngữ yêu cầu !, tôi đặt một khoảng trắng giữa toán tử và toán hạng. Điều này làm cho sự phủ định khó bỏ qua hơn nhiều:

if (! condition) { … }

Lưu ý rằng mọi lập trình viên nên dịch điều này một cách tự động , không cần suy nghĩ thứ hai, để không bị điều kiện trong đầu. Có được sự trôi chảy này trong việc đọc thành ngữ mã là một trong những bước đầu tiên để trở thành một lập trình viên giỏi.


13

Hai là giống nhau về chức năng, vì vậy cái nào để sử dụng là một vấn đề của hương vị.

Lý do chính mà tôi sử dụng == falselà tôi đã thấy rằng !quá dễ bỏ qua, khi xem mã.

Bị cắn nghiêm trọng bởi điều này, tôi đã có thói quen làm cho nó rất rõ ràng khi kiểm tra sai.


Nếu toán tử được đặt tên notnhư trong Pascal, tôi không nghĩ rằng điều này sẽ trở thành một vấn đề.


5
Vì lý do này, một dự án C ++ mà tôi đã làm cho một số phần mềm thiết bị y tế có một tiêu chuẩn mã hóa bắt buộc == falsethay vì !cùng lý do này (để làm cho nó nổi bật). Tuy nhiên, không có yêu cầu sử dụng == true, vì vậy mọi giá trị khác không vẫn hoạt động như bình thường.
tcrosley

12
Tôi luôn thấy lập luận này không thuyết phục - có những vị trí khác trong C / C ++ / C # / Java / etc khi không thấy một ký tự đơn lẻ có tác động đáng kể tương tự đến việc giải thích mã; lẻ loi "!" như là người xấu duy nhất không có ý nghĩa với tôi.
Bevan

5
@bevan Rõ ràng bạn chưa bị cắn.

1
Mặc dù tôi đồng ý rằng nhìn ra !có lẽ là sai lầm rắc rối nhất của loại này, nhưng IMO không nên tạo thói quen viết ==falsemà là viết các bài kiểm tra đơn vị tốt hơn.
rẽ trái

8
@ ThorbjørnRavnAndersen Hoàn toàn ngược lại - Tôi đã bị cắn thường xuyên trong nhiều năm qua mà tôi đã tự dạy mình đọc mọi nhân vật . Tôi không phải là tác giả của tất cả (hoặc thậm chí hầu hết) mã tôi phải đọc hàng ngày, vì vậy mọi quy ước cá nhân mà chúng ta đang thảo luận ở đây đều có giá trị tối thiểu: Tôi cần hiểu chính xác tất cả các mã tôi đọc, không phải chỉ những thứ tôi đã viết.
Bevan


6

bởi vì đôi khi bạn có thể viết boolean = false(với các lỗi rõ ràng) và false == booleankhông có vẻ tự nhiên (cho dù thực tiễn tốt đến đâu)


Cách đây rất lâu khi tôi mới bắt đầu lập trình, một người cố vấn của tôi đã gợi ý tôi nên tập thói quen làm if( INVALID_HANDLE_VALUE == hFile )để tránh những việc như thế. Theo cách đó, nếu bạn trượt lên và sử dụng một dấu bằng thay vì hai, bạn sẽ gặp lỗi trình biên dịch. Rõ ràng điều này chỉ hoạt động khi biểu thức bên trái là một hằng số, nhưng nó đã giúp tôi đỡ đau đầu hơn tôi có thể đếm được.
vẽ Chapin

nếu bạn sử dụng một công cụ phân tích tĩnh, nó sẽ giúp bạn đỡ đau đầu hơn gấp trăm lần và bạn có thể khôi phục lại hFile==INVALID_HANDLE_VALUE văn bản tự nhiên .
Gqqnbig

4

if (!boolean_variable)dịch sang if the condition is not true.

if (boolean == false)dịch sang if the condition not false is true. Bởi vì đó là logic đảo ngược, nó khó hiểu hơn.


3
! đúng nghĩa là không đúng. ! boolean có nghĩa là không sai hoặc không đúng tùy thuộc vào giá trị của boolean, mà chính nó là nghịch đảo logic.
S.Robins

1
@ S.Robins Tôi tìm thấy tên ngu ngốc của boolean cho một biến boolean. Một cái gì đó như ví dụ isVisiblesẽ là một ví dụ tốt hơn. Sau đó, if (!isVisible)có nghĩa là nếu không hiển thị - điều này đơn giản hơn để hiểu sau đó if (isVisible==false), đó là một logic nghịch đảo. Hy vọng nó rõ ràng hơn bây giờ. Hoặc, tôi đã hiểu nhầm ý kiến ​​của bạn?
BЈовић

2

Trong (nhiều) trình biên dịch cũ hơn, tôi tin rằng chúng sẽ chia (boolean == false) thành 2 bài tập đăng ký và một mã so sánh trong ngôn ngữ máy. Ví dụ đầu tiên sẽ được chia thành một phép gán và toán tử KHÔNG. Về hiệu suất, hoạt động so sánh sẽ mất một số chu kỳ xung nhịp, tùy thuộc vào kích thước của thanh ghi được so sánh, so với đảo ngược bit (1 đồng hồ) và sẽ chậm hơn để thực hiện.

Điều đó đang được nói, tôi tin rằng các trình biên dịch mới hơn đã loại bỏ điều này, vì vậy nó cũng ổn để đi với một trong hai.


Tạo mã máy là công việc của người biên dịch, không phải là lập trình viên ngôn ngữ cấp cao ...
CVn

Vì lý do lịch sử, điều này rất có thể là một trong những lý do khiến một phương pháp trở nên được ưa thích hơn phương pháp kia.
Legolas

1

Trong công việc tôi thường giao dịch với Booleans có thể là null nên tôi thường viết mã trường hợp này là

if (value != null && value == true){
    //do something
}

bởi vì cá nhân tôi cảm thấy sự đối xứng làm cho nó dễ đọc hơn. Đặc biệt là nếu có Booleans khác đang được thử nghiệm là tốt.

Tôi không thực sự quan tâm cách này hay cách khác.


4
nếu value == truesau đó không có lý do để kiểm tra rằng nó không phải là null. Nếu value == nullnó không bao giờ nên kích hoạt câu lệnh if ở vị trí đầu tiên, thì if (value)nên là đủ.
zzzzBov

1
Booleans là các đối tượng (trong java) và do đó có thể là null nên chỉ cần nói if (value)ném một ngoại lệ. Tôi sẽ đánh giá cao nếu những người downvote đưa ra lý do.
WuHoUnited

3
Tôi chỉ tình cờ thấy điều này, đã không downvote. Boolean null không phải là thực hành tốt. Tại sao? bởi vì boolean thường đại diện cho trạng thái của một cái gì đó được bật. Trong hầu hết các trường hợp, bạn sẽ muốn khai báo nó sai ngay từ đầu và sau đó thay đổi nó cùng với hành vi. Rất hiếm khi thấy boolean không được khởi tạo.
Aubergine

Tôi phải đồng ý với Aubergine ở đây, bản thân tôi đã rơi vào thói quen xấu (đặc biệt là trong Java) khi để các bool không được khởi tạo và sau đó kết thúc việc kiểm tra null. Tôi nghĩ rằng đây là một lỗ hổng của ngôn ngữ, tuy nhiên trong đó áp đặt lỗ hổng đó cho người dùng. Khi khai báo một biến bool mới, nó sẽ mặc định là false mà không khởi tạo theo ý kiến ​​của tôi.

2
@WuHoUnited, ngay cả khi giá trị là null, value == truesẽ là đủ.
zzzzBov

1

Khi bạn đang kiểm tra điều kiện thực, sẽ rất hợp lý if (condition), đặc biệt là khi bạn áp dụng quy ước đặt tên biến boolean bắt đầu bằng 'is': if (isOpen)hoàn toàn rõ ràng và việc sử dụng != falsesẽ là dư thừa.

Đối với C / C ++ / Java / vv. lập trình viên, ý nghĩa của '!' toán tử hoàn toàn bị đồng hóa, đến mức chúng ta tự động có 'không' trong tâm trí khi chúng ta nhìn thấy nó. Vì vậy, có if (!isOpen)là rõ ràng như if (_NOT_ isOpen)đối với tôi. Nhưng bạn chưa đủ quen thuộc, trong C / C ++, bạn có thể tạo một macro với #define _NOT_ !. Nhưng hãy tin tôi, sau một vài năm điều này là hoàn toàn không cần thiết.

Bên cạnh đó, luôn ưu tiên kiểm tra các giá trị boolean mà không so sánh chúng với nghĩa đen. Chẳng hạn, rất nguy hiểm khi kiểm tra if (x == true)vì giá trị boolean được coi là đúng nếu nó không bằng 0 và đúng theo nghĩa đen chỉ có một giá trị cụ thể, do đó x có thể là 'true' (nghĩa là khác không) và vẫn là phép so sánh đánh giá là sai (vì nó chứa 2 và nghĩa đen là, giả sử, 1.) Tất nhiên điều đó không áp dụng cho việc so sánh với sai, nhưng nếu bạn không sử dụng nó khi kiểm tra là đúng, tại sao lại sử dụng nó khi kiểm tra sai?


Không cần thiết phải tạo macro C ++ mà bạn đề xuất vì C ++ đã hiểu 'không'. Liên quan: stackoverflow.com/questions/2393673/c-and-or-not-xor-keywords
Frozenkoi

Điều đó đúng, nhưng đó chỉ là một từ khóa cho tiêu chuẩn C ++ 0X. Trước đó, nó chỉ là một vĩ mô khác.
Fabio Ceconello

0

Vấn đề kích cỡ ;)

Trong các biểu thức hỗn hợp, nó dễ đọc hơn:

boolean1 = false
boolean2 = true

p ! boolean1 and ! boolean2
p boolean1 == false and boolean2 == false

Và đặc biệt cho ruby ​​một ví dụ, nơi nó là một sự khác biệt lớn:

boolean = nil
p ! boolean         #-> true
p boolean == false  #-> false

nil không sai, nhưng nó cũng không đúng


0

Dựa trên kinh nghiệm của tôi và câu trả lời từ câu hỏi của tôi mà bạn đã liên kết đến.

Một số người thích sử dụng if (điều kiện), vì lý do là nó ngắn hơn để viết. và đối với tôi nó thực sự có ý nghĩa, ví dụ (! isValidated ()) Tôi đọc cái này là Không hợp lệ. nhưng đối với tôi tất cả đều dựa trên sở thích cá nhân và nó phụ thuộc vào cấu trúc logic của phương thức isValidated (), nếu nó trả về đúng hoặc sai


0

Nếu bạn đặt tên cho biến của bạn đúng, thì !booleantự nhiên hơn. Nó đọc như not booleanbất cứ ai đủ lập trình viên để đọc mã về mặt tinh thần.


0

Đối với một số người, ý nghĩa càng sớm được thể hiện càng tốt.

Đối với những người có "nếu! ..." so sánh nhanh hơn với "nếu ..." thì phải đọc qua toàn bộ điều kiện (điều này thực sự có thể khá dài, ví dụ (thisT Breath = thatThing hoặc Something = the other thing) OR ( thinga = thingb và thinga = thingd), v.v.) chỉ để tìm == false ở cuối.

Có cái! (Tôi thực sự thích không phải khi ngôn ngữ cho phép) ngay trước mặt sẽ có tiếng Anh 'không' cho điều kiện này ở đó sớm hơn.

Vấn đề này cũng dẫn đến việc xem xét sử dụng các untilngôn ngữ hỗ trợ nó, ví dụ như 'công cụ chung' cho đến khi mọi thứ hoàn thành. Như những người khác nói, biểu hiện ngôn ngữ tự nhiên là mục tiêu. Tôi thích ví dụ "mặt trời đang tỏa sáng" ở trên.


0

Một lý do khác là nếu bạn đang làm việc trong một cơ sở mã sử dụng nhiều ngôn ngữ, nếu có một cách thành ngữ để làm điều gì đó an toàn trong tất cả các ngôn ngữ, thì bạn nên làm điều đó ở mọi nơi để bạn hình thành thói quen tốt và ít có khả năng đi lên.

Tôi không thể nghĩ đến bất cứ nơi nào if (!variable)(hoặc tương đương như if not variabletùy thuộc vào ngôn ngữ của bạn) không an toàn, trong khi đó, ví dụ như if self.is_ready() == False: ...không an toàn với python nếu self.is_ready()trở về None, bây giờ hoặc trong tương lai, đó sẽ là điều hoàn toàn hợp lý để nó làm cho thấy nó chưa sẵn sàng vì Nonecũng giống như chim ưng False.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.