Dalam C#, (dan merasa bebas untuk jawaban untuk bahasa-bahasa lain), bagaimana agar tidak runtime mengevaluasi logika pernyataan?
Contoh:
DataTable myDt = new DataTable();
if (myDt != null && myDt.Rows.Count > 0)
{
//do some stuff with myDt
}
Yang pernyataan tidak runtime mengevaluasi pertama -
myDt != null
atau:
myDt.Rows.Count > 0
?
Ada waktu ketika compiler akan pernah mengevaluasi pernyataan mundur? Mungkin ketika "ATAU" operator terlibat?
& ini dikenal sebagai logika bitwise operator dan akan selalu mengevaluasi semua sub-ekspresi
Apa contoh yang baik ketika menggunakan bitwise operator, bukan "hubung pendek boolean"?
C# : Kiri ke kanan, dan pengolahan berhenti jika seorang non-match (mengevaluasi ke false) ditemukan.
"C# : Kiri ke kanan, dan pengolahan berhenti jika pertandingan (bernilai true) ditemukan."
Zombie domba adalah salah, tidak cukup rep untuk turun suara itu.
Pertanyaannya adalah tentang && operator, tidak || operator.
Dalam kasus && evaluasi akan berhenti jika PALSU ditemukan.
Dalam kasus || evaluasi berhenti jika BENAR ditemukan.
Saya menyadari pertanyaan ini sudah dijawab, tapi saya'd ingin melempar lain sedikit informasi yang terkait dengan topik.
Dalam bahasa, seperti C++, di mana anda dapat benar-benar overload perilaku && dan || operator, hal ini sangat dianjurkan bahwa anda jangan lakukan ini. Hal ini karena ketika anda overload perilaku ini, anda akhirnya memaksa evaluasi dari kedua sisi operasi. Ini dua hal:
Untuk info lebih lanjut, baca Scott Meyers' buku, Lebih Efektif C++. Cheers!
vb.net
if( x isNot Nothing AndAlso x.go()) then
Anda dapat menggunakan Dan bukan ofAndAlso di vb. dalam hal ini sisi kiri akan dievaluasi pertama juga, tapi sisi kanan akan mendapatkan dievaluasi terlepas dari hasilnya.
Praktik terbaik: Selalu gunakan Danjuga, kecuali anda memiliki alasan yang sangat baik mengapa tidak.
Itu bertanya pada ikutan mengapa atau kapan akan ada yang menggunakan Dan bukan Danjuga (atau & bukan &&): Berikut ini sebuah contoh:
if ( x.init() And y.init()) then
x.process(y)
end
y.doDance()
Dalam hal ini, saya ingin init kedua X dan Y. Y harus diinisialisasi dalam rangka untuk y.DoDance untuk dapat melaksanakan. Namun, di init() fungsi saya juga melakukan beberapa hal ekstra seperti memeriksa soket terbuka, dan hanya jika yang bekerja ok, untuk *kedua*****, aku harus pergi ke depan dan melakukan x.proses(y).
Sekali lagi, ini mungkin tidak diperlukan dan tidak elegan dalam 99% kasus, itulah sebabnya saya mengatakan bahwa default harus digunakan Danjuga.
@shsteimer
konsep kesopanan adalah mengacu pada operator overloading. dalam pernyataan: ... Yang dievaluasi terlebih dahulu, jika mengevaluasi ke false, B adalah tidak pernah dievaluasi. Hal yang sama berlaku untuk
Yang's tidak operator overloading. Operator overloading adalah istilah yang diberikan untuk membiarkan anda mendefinisikan perilaku kustom untuk operator, seperti *, +, =, dan sebagainya.
Ini akan membiarkan anda menulis anda sendiri 'Log' kelas, dan kemudian melakukan
a = new Log(); // Log class overloads the + operator
a + "some string"; // Call the overloaded method - otherwise this wouldn't work because you can't normally add strings to objects.
Lakukan ini
a() || b() // be never runs if a is true
sebenarnya yang disebut Short Circuit Evaluasi
ZombieSheep mati-on. Hanya "gotcha" yang mungkin menunggu adalah bahwa hal ini hanya berlaku jika anda menggunakan && operator. Ketika menggunakan & operator, baik ekspresi akan dievaluasi setiap saat, terlepas jika salah satu atau kedua mengevaluasi ke false.
if (amHungry & whiteCastleIsNearby)
{
// The code will check if White Castle is nearby
// even when I am not hungry
}
if (amHungry && whiteCastleIsNearby)
{
// The code will only check if White Castle is nearby
// when I am hungry
}
Perhatikan bahwa ada perbedaan antara && dan & mengenai berapa banyak ekspresi dievaluasi.
&& ini dikenal sebagai short-circuited boolean AND, dan akan, seperti yang dicatat oleh orang lain di sini, berhenti lebih awal jika hasilnya dapat ditentukan sebelum semua sub-ekspresi yang akan dievaluasi.
& lebih dikenal sebagai logika bitwise operator dan akan selalu mengevaluasi semua sub-ekspresi.
Seperti:
if (a() && b())
Hanya akan panggil b jika a pengembalian benar.
namun, ini:
if (a() & b())
Akan selalu memanggil kedua a dan b, meskipun hasil dari panggilan a adalah palsu dan dengan demikian diketahui palsu terlepas dari hasil menelepon b.
Ini sama ada perbedaan untuk || dan | operator.
Beberapa bahasa memiliki situasi yang menarik di mana ekspresi dieksekusi dalam urutan yang berbeda. Saya secara khusus memikirkan Ruby, tapi aku'm yakin mereka yang dipinjam dari tempat lain (mungkin Perl).
Ekspresi dalam logika akan menginap kiri ke kanan, tapi misalnya:
puts message unless message.nil?
Di atas akan mengevaluasi "pesan.nihil?" pertama, kemudian jika mengevaluasi ke false (kecuali seperti kecuali jika dijalankan ketika kondisi ini palsu bukan yang sebenarnya), "menempatkan pesan" akan mengeksekusi, yang mencetak isi variabel pesan ke layar.
It's jenis cara yang menarik untuk struktur kode anda kadang-kadang... saya pribadi ingin menggunakannya untuk waktu yang sangat singkat 1 liners seperti di atas.
Edit:
Untuk membuatnya sedikit lebih jelas, di atas adalah sama seperti:
unless message.nil?
puts message
end
Konsep kesederhanaan adalah mengacu pada operator overloading. dalam pernyataan:
if( A && B){
// do something
}
Yang dievaluasi terlebih dahulu, jika mengevaluasi ke false, B adalah tidak pernah dievaluasi. Hal yang sama berlaku untuk
if(A || B){
//do something
}
Yang dievaluasi terlebih dahulu, jika mengevaluasi ke true, B adalah tidak pernah dievaluasi.
Konsep ini, overloading, berlaku untuk (saya pikir) semua C gaya bahasa, dan banyak orang lain juga.
Apa adalah contoh yang baik ketika menggunakan bitwise operator, bukan "hubung pendek boolean"?
Misalkan anda memiliki bendera, mengatakan untuk atribut file. Misalkan anda've didefinisikan BACA 4, MENULIS sebagai 2, dan EXEC sebagai 1. Dalam biner, yang's:
READ 0100
WRITE 0010
EXEC 0001
Bendera masing-masing memiliki satu bit set, dan masing-masing adalah unik. Bitwise operator memungkinkan anda untuk menggabungkan bendera ini:
flags = READ & EXEC; // value of flags is 0101
Ketika hal-hal yang semua in-line, mereka're dieksekusi kiri-ke-kanan.
Ketika hal-hal yang bersarang, mereka're dieksekusi batin-ke-luar. Ini mungkin tampak membingungkan karena biasanya apa yang's "terdalam" di sisi kanan dari garis, sehingga tampaknya seperti itu's akan mundur...
Misalnya
a = Foo( 5, GetSummary( "Orion", GetAddress("Orion") ) );
Hal-hal yang terjadi seperti ini:
GetAddress
dengan literal "Orion"
GetSummary
dengan literal "Orion"
dan hasil dari GetAddress
Foo
dengan literal 5
dan hasil dari GetSummary
a
Saya suka Orion's tanggapan. I'll menambahkan dua hal:
Katakan kita memiliki contoh berikut:
a = Foo(5, GetSummary("Orion", GetAddress("Orion")),
GetSummary("Chris", GetAddress("Chris")));
Berikut ini's urutan eksekusi:
GetAddress("Orion")
GetSummary("Orion", ...)
GetAddress("Chris")
GetSummary("Chris", ...)
Foo(...)
a
Saya dapat't berbicara tentang C#'s persyaratan hukum (meskipun saya melakukan tes serupa contoh menggunakan Mono sebelum menulis posting ini), tapi perintah ini dijamin di Jawa.
Dan hanya untuk kelengkapan (karena ini adalah bahasa-agnostik thread juga), ada bahasa seperti C dan C++, dimana urutan tidak dijamin kecuali ada urutan titik. Referensi: 1, 2. Dalam menjawab thread's pertanyaan, namun, &&
dan ||
adalah urutan poin dalam C++ (kecuali overload; juga lihat OJ's jawaban yang sangat baik). Sehingga beberapa contoh:
foo() && bar()
foo() & bar()
Di &&
kasus foo()
dijamin untuk menjalankan sebelum bar()
(jika yang terakhir ini berjalan sama sekali), karena &&
adalah urutan titik. Di &
kasus, tidak ada jaminan tersebut dilakukan (dalam C dan C++), dan memang bar()
dapat dijalankan sebelum foo()
, atau sebaliknya.
D bahasa pemrograman Tidak melakukan kiri-ke-kanan evaluasi dengan hubungan arus pendek dan doesn't memungkinkan overloading dari &&
dan '||' operator.
Itu bertanya pada ikutan mengapa atau kapan akan ada yang menggunakan Dan bukan Danjuga (atau & bukan &&): Berikut ini adalah sebuah contoh:
jika ( x.init() Dan y.init()) kemudian x.proses(y) end y.doDance()
Dalam hal ini, saya ingin init kedua X dan Y. Y harus diinisialisasi dalam rangka untuk y.DoDance untuk dapat melaksanakan. Namun, di init() fungsi saya juga melakukan beberapa hal ekstra seperti memeriksa soket terbuka, dan hanya jika yang bekerja ok, kedua, aku harus pergi ke depan dan melakukan x.proses(y).
Saya percaya ini agak membingungkan. Meskipun misalnya anda bekerja,'s bukan kasus yang khas untuk menggunakan Dan
(dan mungkin saya akan menulis hal yang berbeda untuk membuatnya lebih jelas). Dan
(&
dalam kebanyakan bahasa lain) adalah benar-benar bitwise dan operasi. Anda akan menggunakan ini untuk menghitung operasi bit, misalnya menghapus bendera bit atau masking dan pengujian bendera:
Dim x As Formatting = Formatting.Bold Or Formatting.Italic
If (x And Formatting.Italic) = Formatting.Italic Then
MsgBox("The text will be set in italic.")
End If
Anda menggunakan & ketika anda secara khusus ingin mengevaluasi semua sub-ekspresi, kemungkinan besar karena mereka memiliki efek samping yang anda inginkan, meskipun hasil akhir akan palsu dan dengan demikian tidak dapat menjalankan anda kemudian bagian dari anda jika-pernyataan.
Perhatikan bahwa & dan | beroperasi untuk investasi bitwise masker dan nilai-nilai boolean dan tidak hanya untuk bitwise operasi. Mereka're disebut bitwise, tetapi mereka yang ditetapkan untuk kedua integer dan boolean tipe data di C#.