Mengapa &&
lebih disukai daripada &
dan ||
lebih disukai |
?
Saya bertanya kepada seseorang yang telah memprogram selama bertahun-tahun dan penjelasannya adalah:
Misalnya, dalam if (bool1 && bool2 && bool3) { /*DoSomething*/ }
, bool1
harus benar agar dapat menguji bool2
mana yang harus benar sebelum melanjutkan ke bool3
, dll. Jika saya menggunakan satu &
saja, tidak ada urutan untuk pengujian bahkan jika semuanya harus benar untuk maju ke baris berikutnya, jadi mengapa itu penting?
Catatan: Saya ingin menunjukkan bahwa saya adalah pemograman yang setara dengan balita dan ini bukan pertanyaan serius atau mendesak. Ini lebih merupakan masalah memahami mengapa sesuatu harus dilakukan dengan cara tertentu dan bukan dengan cara lain.
x & y
danx && y
akan selalu dievaluasi ke hasil yang sama jika x dan y adalah ekspresi tipe boolean. Nyatanya, satu-satunya perbedaan dalam kasus itu tampaknya adalah bahwa dalamx & y
, y selalu dievaluasi.Jawaban:
Dalam kebanyakan kasus,
&&
dan||
lebih disukai daripada&
dan|
karena yang pertama korsleting, artinya evaluasi dibatalkan segera setelah hasilnya jelas.Contoh:
if(CanExecute() && CanSave()) { }
Jika
CanExecute
dikembalikanfalse
, ekspresi lengkapnya akanfalse
, terlepas dari nilai yang dikembalikanCanSave
. Karena itu,CanSave
tidak dieksekusi.Ini sangat berguna dalam situasi berikut:
string value; if(dict.TryGetValue(key, out value) && value.Contains("test")) { // Do Something }
TryGetValue
kembalifalse
jika kunci yang disediakan tidak ditemukan dalam kamus. Karena sifat hubungan pendek&&
,value.Contains("test")
hanya dijalankan, ketikaTryGetValue
kembalitrue
dan dengan demikianvalue
tidaknull
. Jika Anda akan menggunakan operator bitwise AND&
, Anda akan mendapatkan aNullReferenceException
jika kunci tidak ditemukan dalam kamus, karena bagian kedua dari ekspresi dieksekusi dalam kasus apa pun.Contoh serupa tetapi lebih sederhana dari ini adalah kode berikut (seperti yang disebutkan oleh TJHeuvel):
if(op != null && op.CanExecute()) { // Do Something }
CanExecute
hanya dijalankan jikaop
tidaknull
. Jikaop
adalahnull
, bagian pertama dari ekspresi (op != null
) mengevaluasi kefalse
dan evaluasi sisanya (op.CanExecute()
) adalah dilewati.Terlepas dari ini, secara teknis, mereka berbeda, juga:
&&
dan||
hanya dapat digunakan padabool
sedangkan&
dan|
dapat digunakan pada setiap tipe integral (bool
,int
,long
,sbyte
, ...), karena mereka adalah operator bitwise.&
adalah bitwise AND operator dan|
adalah bitwise OR operator.Tepatnya, di C #, operator tersebut (
&
,|
[dan^
]) disebut "Operator logika" (lihat spesifikasi C # , bab 7.11). Ada beberapa implementasi dari operator ini:int
,uint
,long
danulong
, Bab 7.11.1):Mereka diimplementasikan untuk menghitung hasil bitwise dari operan dan operator, yaitu
&
adalah menerapkan untuk menghitung bitwise logisAND
dllMereka dilaksanakan untuk melakukan operasi logis dari jenis pencacahan yang mendasari.
Hasilnya tidak dihitung menggunakan kalkulasi bitwise. Hasilnya pada dasarnya dicari berdasarkan nilai dari dua operan, karena jumlah kemungkinannya sangat kecil.
Karena kedua nilai digunakan untuk pencarian, implementasi ini tidak mengalami hubungan arus pendek.
sumber
if(op != null && op.CanExecute())
. Karena penyebab kedua tidak dievaluasi saat isnt pertama tidak benar, ini valid.TryGetValue
contoh saya . Tapi ya, itu contoh bagus lainnya.&
atau|
digunakan dengan argumen non-bool (yaitu apa yang dilakukan operator) untuk kepentingan semua orang baru.Untuk menjelaskan dengan sangat jelas apa artinya ini (meskipun jawaban lain mengisyaratkan - tetapi mungkin menggunakan terminologi yang tidak Anda mengerti).
Kode berikut:
if (a && b) { Foo(); }
Benar-benar dikompilasi untuk ini:
if (a) { if (b) { Foo(); } }
Di mana kode berikut dikompilasi persis seperti yang diwakili:
if (a & b) { Foo(); }
Ini disebut korsleting. Secara umum Anda harus selalu menggunakan
&&
dan||
dalam kondisi Anda.Tanda Bonus: Ada satu skenario yang seharusnya tidak Anda lakukan. Jika Anda berada dalam situasi di mana kinerja sangat penting (dan ini penting nano-detik ) hanya gunakan hubungan pendek ketika Anda harus (misalnya
null
memeriksa) - karena hubungan pendek adalah cabang / lompatan; yang dapat mengakibatkan kesalahan prediksi cabang pada CPU Anda; sebuah&
jauh lebih murah daripada&&
. Ada juga skenario di mana arus pendek benar-benar dapat memutus logika - lihat jawaban saya ini.Diatribe / Monologue : Mengenai kesalahan prediksi cabang yang diabaikan dengan sangat bahagia. Mengutip Andy Firth (yang telah mengerjakan game selama 13 tahun): "Ini mungkin level yang lebih rendah dari yang orang-orang pikir mereka harus pergi ... tapi mereka salah. Memahami bagaimana perangkat keras yang Anda pemrograman untuk memperlakukan cabang dapat mempengaruhi kinerja ke tingkat BESAR ... jauh lebih dari yang mungkin dihargai oleh kebanyakan pemrogram re: kematian oleh seribu pemotongan. "
Berikut adalah patokan bagi kafir. Yang terbaik adalah menjalankan proses dalam RealTime / High untuk mengurangi efek penjadwal: https://gist.github.com/1200737
sumber
(x && y)
diterjemahkan keLOAD x; BRANCH_FALSE; LOAD y; BRANCH_FALSE;
mana(x & y)
diterjemahkan menjadiLOAD x; LOAD y; AND; BRANCH_FALSE;
. Satu cabang versus dua.Operator logika (
||
dan&&
) vs. operator bitwise (|
dan&
).Perbedaan paling penting antara operator logika dan operator bitwise adalah bahwa operator logika mengambil dua boolean dan menghasilkan boolean sementara operator bitwise mengambil dua bilangan bulat dan menghasilkan bilangan bulat (catatan: bilangan bulat berarti tipe data integral apa pun, bukan hanya int).
Untuk menjadi bertele-tele, operator bitwise mengambil pola bit (mis. 01101011) dan melakukan sedikit DAN / ATAU pada setiap bit. Jadi, misalnya jika Anda memiliki dua bilangan bulat 8-bit:
a = 00110010 (in decimal: 32+16+2 = 50) b = 01010011 (in decimal: 64+ 16+2+1 = 83) ---------------- a & b = 00010010 (in decimal: 16+2 = 18) a | b = 01110011 (in decimal: 64+32+16+2+1 = 115)
sedangkan operator logika hanya bekerja di
bool
:a = true b = false -------------- a && b = false a || b = true
Kedua, sering kali mungkin untuk menggunakan operator bitwise pada bool karena true dan false masing-masing setara dengan 1 dan 0, dan jika Anda menerjemahkan true ke 1 dan false ke 0, lalu lakukan operasi bitwise, lalu ubah bukan nol menjadi benar dan nol menjadi salah; Kebetulan hasilnya akan sama jika Anda baru saja menggunakan operator logika (periksa ini untuk latihan).
Perbedaan penting lainnya adalah bahwa operator logika dihubung pendek . Karenanya, di beberapa lingkaran [1], Anda sering melihat orang melakukan hal seperti ini:
if (person && person.punch()) { person.doVictoryDance() }
yang diterjemahkan menjadi: "jika orang itu ada (yaitu bukan nol), cobalah untuk meninju dia, dan jika pukulan itu berhasil (yaitu kembali benar), maka lakukan tarian kemenangan" .
Jika Anda menggunakan operator bitwise, ini:
if (person & person.punch()) { person.doVictoryDance() }
akan diterjemahkan menjadi: "jika orang itu ada (yaitu bukan nol) dan pukulan berhasil (yaitu mengembalikan nilai true), maka lakukan tarian kemenangan" .
Perhatikan bahwa di operator logika hubung pendek,
person.punch()
kode tidak dapat dijalankan sama sekali jikaperson
null. Faktanya, dalam kasus khusus ini, kode kedua akan menghasilkan kesalahan referensi nol jikaperson
nol, karena mencoba memanggilperson.punch()
tidak peduli apakah orang itu nol atau tidak. Perilaku tidak mengevaluasi operan kanan ini disebut hubung singkat .[1] Beberapa pemrogram akan menolak untuk menempatkan pemanggilan fungsi yang memiliki efek samping di dalam
if
ekspresi, sementara untuk pemrogram lain itu adalah ungkapan yang umum dan sangat berguna.Karena operator bitwise bekerja pada 32-bit dalam satu waktu (jika Anda menggunakan mesin 32-bit), ini dapat menghasilkan kode yang lebih elegan dan lebih cepat jika Anda perlu membandingkan sejumlah besar kondisi, mis.
int CAN_PUNCH = 1 << 0, CAN_KICK = 1 << 1, CAN_DRINK = 1 << 2, CAN_SIT = 1 << 3, CAN_SHOOT_GUNS = 1 << 4, CAN_TALK = 1 << 5, CAN_SHOOT_CANNONS = 1 << 6; Person person; person.abilities = CAN_PUNCH | CAN_KICK | CAN_DRINK | CAN_SIT | CAN_SHOOT_GUNS; Place bar; bar.rules = CAN_DRINK | CAN_SIT | CAN_TALK; Place military; military.rules = CAN_SHOOT_CANNONS | CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT; CurrentLocation cloc1, cloc2; cloc1.usable_abilities = person_abilities & bar_rules; cloc2.usable_abilities = person_abilities & military_rules; // cloc1.usable_abilities will contain the bit pattern that matches `CAN_DRINK | CAN_SIT` // while cloc2.usable_abilities will contain the bit pattern that matches `CAN_PUNCH | CAN_KICK | CAN_SHOOT_GUNS | CAN_SIT`
Melakukan hal yang sama dengan operator logika akan membutuhkan banyak perbandingan:
Person person; person.can_punch = person.can_kick = person.can_drink = person.can_sit = person.can_shoot_guns = true; person.can_shoot_cannons = false; Place bar; bar.rules.can_drink = bar.rules.can_sit = bar.rules.can_talk = true; bar.rules.can_punch = bar.rules.can_kick = bar.rules.can_shoot_guns = bar.rules.can_shoot_cannons = false; Place military; military.rules.can_punch = military.rules.can_kick = military.rules.can_shoot_guns = military.rules.can_shoot_cannons = military.rules.can_sit = true; military.rules.can_drink = military.rules.can_talk = false; CurrentLocation cloc1; bool cloc1.usable_abilities.can_punch = bar.rules.can_punch && person.can_punch, cloc1.usable_abilities.can_kick = bar.rules.can_kick && person.can_kick, cloc1.usable_abilities.can_drink = bar.rules.can_drink && person.can_drink, cloc1.usable_abilities.can_sit = bar.rules.can_sit && person.can_sit, cloc1.usable_abilities.can_shoot_guns = bar.rules.can_shoot_guns && person.can_shoot_guns, cloc1.usable_abilities.can_shoot_cannons = bar.rules.can_shoot_cannons && person.can_shoot_cannons cloc1.usable_abilities.can_talk = bar.rules.can_talk && person.can_talk; bool cloc2.usable_abilities.can_punch = military.rules.can_punch && person.can_punch, cloc2.usable_abilities.can_kick = military.rules.can_kick && person.can_kick, cloc2.usable_abilities.can_drink = military.rules.can_drink && person.can_drink, cloc2.usable_abilities.can_sit = military.rules.can_sit && person.can_sit, cloc2.usable_abilities.can_shoot_guns = military.rules.can_shoot_guns && person.can_shoot_guns, cloc2.usable_abilities.can_talk = military.rules.can_talk && person.can_talk, cloc2.usable_abilities.can_shoot_cannons = military.rules.can_shoot_cannons && person.can_shoot_cannons;
Contoh klasik di mana pola bit dan operator bitwise digunakan dalam izin sistem file Unix / Linux.
sumber
Dalam kasus:
if (obj != null && obj.Property == true) { }
akan bekerja seperti yang diharapkan.
Tapi:
if (obj != null & obj.Property == true) { }
berpotensi memunculkan pengecualian referensi null.
sumber
Singkat dan sederhana:
1 && 2
= benarkarena
1 = benar (bukan nol) di C
2 = benar (bukan nol) di C
true
ANDS secara logis dengantrue
memberitrue
.Tapi
1 & 2
= 0 = falsekarena
1 = 0001 dalam biner
2 = 0010 dalam biner
0001 ANDs bitwise dengan 0010 menghasilkan 0000 = 0 dalam desimal.
Begitu juga untuk || dan | operator juga ...!
sumber
1 && 2
ilegal di C #&&
adalah versi sirkuit pendek dari&
.Jika kita mengevaluasi
false & true
, kita sudah tahu dari argumen pertama bahwa hasilnya akan salah. The&&
versi operator akan mengembalikan hasil secepat itu bisa, daripada mengevaluasi ekspresi keseluruhan. Ada juga versi|
operator yang serupa||
,.sumber
if (list.Count() > 14 && list[14] == "foo")
aman
if (list.Count() > 14 & list[14] == "foo")
akan macet jika daftar tidak memiliki ukuran yang tepat.
sumber
C # Operator harus menjelaskan alasannya:
Pada dasarnya memiliki dua
&
atau|
's berarti itu bersyarat daripada logis, sehingga Anda dapat membedakan antara keduanya.& Operator memiliki contoh untuk menggunakannya
&
.sumber
Oke, secara nominal
Boolean a = true; Boolean b = false; Console.WriteLine("a({0}) && b({1}) = {2}", a, b, a && b); Console.WriteLine("a({0}) || b({1}) = {2}", a, b, a || b); Console.WriteLine("a({0}) == b({1}) = {2}", a, b, a == b); Console.WriteLine("a({0}) & b({1}) = {2}", a, b, a & b); Console.WriteLine("a({0}) | b({1}) = {2}", a, b, a | b); Console.WriteLine("a({0}) = b({1}) = {2}", a, b, a = b);
menghasilkan jawaban yang sama. Namun, seperti yang Anda tunjukkan, jika Anda memiliki pertanyaan yang lebih kompleks, jadi:
if (a and b and c and d) ..
Jika
a
tidak benar dan mungkinb
merupakan fungsi yang harus dimatikan, sambungkan ke sesuatu, dapatkan ini, lakukan itu, buat keputusan .. mengapa repot-repot? Buang-buang waktu, Anda tahu itu sudah gagal. Mengapa membuat mesin mati dan melakukan pekerjaan ekstra yang tidak berguna?Saya selalu menggunakan
&&
karena saya mengutamakan yang paling mungkin gagal, ergo, lebih sedikit perhitungan sebelum melanjutkan ketika tidak ada gunanya. Jika tidak ada cara untuk memprediksi pilihan yang kurang mungkin, seperti Anda memiliki boolean untuk membatasi keluaran data, sesuatu seperti:if (limit && !MyDictionary.ContainsKey("name")) continue;
Jika tidak
limit
, jangan repot-repot memeriksa kunci, yang bisa memakan waktu lebih lama ..sumber
Ketika digunakan dalam ekspresi logis seperti pernyataan if
&&
lebih disukai karena akan berhenti mengevaluasi ekspresi segera setelah hasil salah pertama ditemukan. Ini dimungkinkan karena nilai salah akan menyebabkan seluruh ekspresi menjadi salah. Demikian pula (dan lagi dalam ekspresi logis)||
lebih disukai karena ini akan berhenti mengevaluasi ekspresi segera setelah menemukan ekspresi yang benar karena nilai benar apa pun akan menyebabkan seluruh ekspresi menjadi benar.Namun, jika ekspresi menjadi atau-ed atau dan-ed bersama-sama memiliki efek samping, dan Anda ingin semua ini terjadi sebagai hasil dari ekspresi Anda (terlepas dari hasil ekspresi logis), maka
&
dan|
dapat digunakan. Sebaliknya, operator&&
dan||
dapat berguna sebagai pelindung dari efek samping yang tidak diinginkan (seperti pointer nol yang menyebabkan pengecualian dilempar).Itu
&
dan|
operator juga dapat digunakan dengan bilangan bulat dan dalam hal ini mereka menghasilkan hasil bilangan bulat yang merupakan dua operan dan-ed atau atau-ed bersama-sama di tingkat bit. Ini dapat berguna ketika bit biner nilai integer digunakan sebagai larik nilai benar dan salah. Untuk menguji apakah bit tertentu aktif atau nonaktif, bit-mask adalah bitwise dan diberi nilai. Untuk menyalakannya sedikit, topeng yang sama dapat diberi bitwise atau diberi nilai. Akhirnya untuk mematikan sedikit, pelengkap bitwise (penggunaan~
) topeng adalah bitwise dan-ed dengan nilainya.int a = 0; // 0 means all bits off a = a | 4; // set a to binary 100 if ((a & 4) != 0) { // will do something } a = a & (~4) // turn bit off again, a is now 000
Dalam bahasa selain C #, harus berhati-hati dengan mode logis versus bitwise dari & dan |. Pada kode di atas, file
if
ekspresi kondisional pernyataan(a & 4) != 0
adalah cara yang aman untuk mengekspresikan kondisi ini, tetapi dalam banyak bahasa seperti C, pernyataan bersyarat dapat dengan mudah memperlakukan nilai bilangan bulat nol sebagai nilai bilangan bulat salah dan bukan nol sebagai benar. (Alasan untuk ini berkaitan dengan instruksi prosesor cabang bersyarat yang tersedia, dan hubungannya dengan bendera nol yang diperbarui setelah setiap operasi bilangan bulat.) Jadiìf
, pengujian pernyataan untuk nol dapat dihapus dan kondisi dapat dipersingkat menjadi(a & 4)
.Hal ini dapat menyebabkan kebingungan dan bahkan mungkin masalah ketika ekspresi digabungkan menggunakan bitwise dan operator mengembalikan nilai yang tidak memiliki bit yang berbaris. Pertimbangkan contoh berikut di mana efek samping dari dua fungsi diinginkan, sebelum memeriksa apakah keduanya berhasil (sebagaimana didefinisikan oleh mereka mengembalikan nilai bukan nol):
if (foo() & bar()) { // do something }
Di C, jika
foo()
mengembalikan 1 danbar()
mengembalikan 2, "sesuatu" tidak akan dilakukan karena1 & 2
nol.C # membutuhkan pernyataan kondisional seperti
if
memiliki oeprand boolean, dan bahasa tidak mengizinkan nilai integer untuk dimasukkan ke nilai boolean. Jadi kode di atas akan menghasilkan kesalahan kompiler. Ini akan lebih tepat diungkapkan sebagai berikut:if (foo() != 0 & bar() != 0) { // do something }
sumber
Jika Anda adalah programmer C lama, berhati-hatilah . C # benar-benar mengejutkan saya.
MSDN mengatakan untuk
|
operator:(Penekanan adalah milik saya.) Jenis Boolean ditangani secara khusus, dan dalam konteks ini pertanyaannya hanya mulai masuk akal, dan perbedaannya adalah, seperti yang telah dijelaskan lainnya dalam jawaban mereka:
dan apa yang lebih disukai tergantung pada banyak hal seperti efek samping, kinerja, dan keterbacaan kode, tetapi umumnya operator hubungan pendek lebih disukai juga karena mereka lebih dipahami oleh orang-orang dengan latar belakang serupa seperti saya.
Alasannya adalah: Saya akan berargumen seperti ini: Karena tidak ada tipe boolean nyata di C, Anda dapat menggunakan operator bitwise
|
dan hasilnya dievaluasi sebagai benar atau salah dalam kondisi if. Tapi ini sikap yang salah untuk C #, karena sudah ada kasus khusus untuk tipe boolean.sumber
Ini penting, karena jika biaya evaluasi bool2 (misalnya) tinggi tetapi bool1 salah, Anda telah menghemat sedikit komputasi dengan menggunakan && over &
sumber
Karena
&&
dan||
digunakan untuk kontrol aliran seperti apaif/else
adanya. Ini tidak selalu tentang persyaratan. Masuk akal untuk menulis sebagai pernyataan, bukan sebagaiif
atauwhile
bersyarat, berikut ini:atau bahkan
Bukan hanya karena
if/else
versi tersebut lebih mudah diketik daripada versi yang setara ; mereka juga lebih mudah dibaca dan dipahami.sumber
&& dan & berarti dua hal yang sangat berbeda dan memberi Anda dua jawaban yang berbeda.
1 && 2
menghasilkan 1 ("true")1 & 2
menghasilkan 0 ("false")&&
adalah operator logika - itu berarti "benar jika kedua operan benar"&
adalah perbandingan bitwise. Artinya "beri tahu saya bit mana yang disetel di kedua operan"sumber
1 && 2
memberikan kesalahan kompiler: "Kesalahan 4 Operator '&&' tidak dapat diterapkan ke operan jenis 'int' dan 'int'"Cara tercepat (dan sedikit bodoh) untuk menjelaskan ini kepada orang-orang yang tidak PERLU mengetahui operasi kode yang tepat saat melakukan ini adalah
&& sedang memeriksa masing-masing kondisi tersebut Hingga menemukan salah dan mengembalikan seluruh hasil sebagai salah
|| sedang memeriksa masing-masing kondisi tersebut Hingga menemukan nilai benar dan mengembalikan keseluruhan hasil sebagai benar.
& sedang melakukan apon berbasis MATHS KEDUA / SEMUA kondisi dan menangani hasilnya.
| sedang melakukan apon berbasis MATHS KEDUA / SEMUA kondisi dan menangani hasilnya.
Saya tidak pernah menemukan titik di mana saya perlu menggunakan & atau |dalam pernyataan if. Saya kebanyakan menggunakannya untuk memotong nilai Heksadesimal menjadi warna komponennya menggunakan pergeseran bitwise.
MISALNYA:
r = fullvalue >> 0xFF & 0xFF; g = fullvalue >> 0xF & 0xFF; b = fullvalue & 0xFF;
Dalam operasi ini "& 0xFF" memaksa untuk hanya melihat nilai biner. Saya pribadi belum menemukan kegunaan untuk | Namun demikian.
sumber
Secara sederhana,
if exp1 && exp2
jika exp1 adalah
flase
jangan centang exp2tapi
if exp1 & exp2
jika exp1 adalah
false
Atautrue
periksa exp2dan jarang orang menggunakan
&
karena mereka jarang ingin memeriksa exp2 jika exp1 adalahfalse
sumber