Atau versus OrElse

95

Apa perbedaan antara or dan OrElse ?

if temp is dbnull.value or temp = 0

menghasilkan kesalahan:

Operator '=' tidak ditentukan untuk tipe 'DBNull' dan tipe 'Integer'.

sementara yang ini bekerja seperti jimat !?

if temp is dbnull.value OrElse temp = 0
OrElse
sumber

Jawaban:

145

OrElseadalah operator korsleting , Orbukan.

Menurut definisi operator boolean 'atau', jika suku pertama Benar maka keseluruhannya pasti benar - jadi kita tidak perlu mengevaluasi suku kedua.

OrElsemengetahui hal ini, jadi jangan mencoba dan mengevaluasi temp = 0setelah itu ditetapkantemp Is DBNull.Value

Ortidak mengetahui hal ini, dan akan selalu berusaha mengevaluasi kedua istilah tersebut. Ketika temp Is DBNull.Value, tidak bisa dibandingkan dengan nol, jadi jatuh.

Anda harus menggunakan ... yah, mana saja yang masuk akal.

AakashM
sumber
2
Jadi Atau hanya masuk akal ketika saya memanggil fungsi setelah atau yang memiliki efek samping bergantung pada kode saya?
Ralph M. Rickenbach
4
Atau masuk akal dalam semua kasus di mana item kedua tidak memicu kesalahan jika yang pertama benar ...
kagum
4
@ Malach: Saya kira begitu (Anda benar-benar mendapatkan perilaku OrElse sebagai default di sebagian besar bahasa lain): Bukan ide yang baik untuk memanggil fungsi dengan efek samping dalam kondisi majemuk itu membuat kode tidak dapat dibaca.
Utaal
4
@ awe: ya, tapi mengapa Anda bahkan ingin membuang waktu mengevaluasi sesuatu yang menurut definisi tidak akan mengubah hasil ekspresi?
Utaal
3
@ MarkJ: Saya tidak benar-benar berpikir empat karakter tambahan mengganggu keterbacaan. Di sisi lain, menggunakan operator yang bergantung pada adanya efek samping (seperti yang ditulis malach) menjadi bermakna terdengar seperti ide yang buruk (dan dapat membuat keterbacaan lebih sulit!). Saya akan menganggap efek samping di tempat-tempat seperti itu sangat tidak-tidak, dan tidak dapat memikirkan situasi apa pun di mana saya lebih suka "Atau" daripada "OrElse". Sayangnya operator ini bekerja seperti ini, karena perilaku "OrElse" mungkin adalah yang paling diharapkan bahkan saat menggunakan "Atau" (terutama jika berasal dari bahasa lain).
Kjartan
42

Ini adalah perilaku yang sama seperti pada C #, di mana setiap orang menggunakan Coditional Or (||) dan Conditional And (&&), di mana Anda juga memiliki Or (|) dan normal And (&). Jadi membandingkan C # dengan VB.Net adalah:

| => Atau

|| => Atau Lain

& => Dan

&& => Dan Juga

Operator boolean bersyarat sangat berguna untuk mencegah bersarang jika ada konstruksi. Namun terkadang operator boolean normal diperlukan untuk memastikan mencapai kedua jalur kode.

Bert Heesbeen
sumber
9
Saya tidak pernah benar-benar tahu ini tersedia. Terima kasih atas informasi baru. Senang mengetahuinya, meskipun saya tidak bisa melihat situasi apa pun yang ingin saya gunakan "|". Saya pikir itu akan membutuhkan kondisi kedua untuk menyebabkan efek samping masuk akal, dan itu sendiri tidak masuk akal menurut saya! ;)
Kjartan
7
Eh, sejauh yang saya tahu, |dan &operator bitwise di C #, bukan operasi boolean sama sekali.
Nyerguds
8

OrElse dihubung pendek , ini berarti bahwa hanya satu sisi ekspresi yang akan diuji jika sisi pertama cocok.

Sama seperti AndAlso hanya akan menguji satu sisi ekspresi jika paruh pertama gagal.

stevehipwell.dll
sumber
4

(Saya telah melihat jawaban lain dan menyadari bahwa saya sangat salah)

Operator OrElse "melakukan disjungsi logika hubung singkat pada dua ekspresi", artinya: jika operan kiri benar dan seluruh ekspresi dijamin benar, operan kanan bahkan tidak akan dievaluasi (ini berguna dalam kasus seperti:

string a;
//...
if (a is null) or (a = "Hi") //...

untuk menghindari lemparan NullReferenceException oleh operan kanan.

Saya sangat heran bahwa ini ( evaluasi malas ) bukanlah perilaku default ordan andseperti di C / C ++ dan C # (dan banyak bahasa lainnya ...)

Utaal
sumber
7
Masalahnya, di VB klasik, hanya ada And dan Or, yang tidak mengalami hubungan arus pendek. Saya rasa saya benar saat mengatakan bahwa beta pertama VB.NET benar-benar mengubah perilaku operator ini - ada keributan, jadi mereka diubah kembali dan AndAlso dan OrElse (hubungan arus pendek) diperkenalkan. Saya hanya bisa membayangkan nama alternatif yang harus mereka pertimbangkan jika ini adalah yang terbaik ...
AakashM
1
Dengan menyediakan Or dan OrElse (| dan || di C #) ini memungkinkan pengembang untuk memilih bagaimana mereka menangani kode mereka sendiri. Menggunakan kode di atas, saya harus menggunakan try catch di sekitarnya untuk menangani nilai null dalam variabel a. OrElse memungkinkan pengembang untuk menangani ini di pernyataan if lain sebagai hasil yang mungkin diketahui daripada pengecualian. Ini lebih jelas jika variabel a adalah parameter dalam suatu metode, di mana Anda memiliki kontrol yang lebih sedikit ketika variabel diberi nilai (yaitu di luar metode)
Kevin Hogg
Hubung singkat juga bukan perilaku default OR dan AND di c #. c # memiliki dua operator berbeda untuk operasi bitwise dan logis / hubungan pendek. && dan || melakukan perbandingan logis , dan mengembalikan nilai boolean The & dan | operator bersifat bitwise dan mengembalikan nilai integer. Jadi dimana 1 || 2 mengembalikan "true", 1 | 2 mengembalikan "3".
TomXP411
4

OrElse mengevaluasi ekspresi pertama kemudian jika benar itu akan melanjutkan ke pernyataan sementara OR mengevaluasi dua ekspresi sebelum akan melanjutkan ke pernyataan mereka.

Contoh:

Textbox1.Text= 4

Textbox2.Text= ""

Menggunakan OrElse

  If TextBox1.Text > 2 OrElse TextBox2.Text > 3 Then
      MsgBox("True")
  End If

Hasilnya: BENAR


Menggunakan ATAU

 If TextBox1.Text > 2 Or TextBox2.Text > 3 Then

            MsgBox("True")
  End If

Hasilnya adalah: Error tidak dapat mengubah string menjadi double.

Larz
sumber
3

Jawaban Bert tidak terlalu akurat. '|' atau '&' adalah operator logika, di C #, ini selalu diperlakukan sebagai operator bit, lihat kode berikut sebagai contoh

        static void Main()
        {
            object a = null;
            int b = 3;
            if (a == null | a.ToString() == "sdffd")
            {
                Console.WriteLine("dddd");
            }
            Console.WriteLine(b | b);
            Console.Read();
        }

Berikut ini adalah IL

    .method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       62 (0x3e)
  .maxstack  3
  .locals init ([0] object a,
           [1] int32 b,
           [2] bool CS$4$0000)
   IL_0000:  nop
   IL_0001:  ldnull
   IL_0002:  stloc.0
   IL_0003:  ldc.i4.3
   IL_0004:  stloc.1
   IL_0005:  ldloc.0
   IL_0006:  ldnull
   IL_0007:  ceq
   IL_0009:  ldloc.0
   IL_000a:  callvirt   instance string [mscorlib]System.Object::ToString()
   IL_000f:  ldstr      "sdffd"
   IL_0014:  call       bool [mscorlib]System.String::op_Equality(string,
                                                                 string)
   IL_0019:  or
   IL_001a:  ldc.i4.0
   IL_001b:  ceq
   IL_001d:  stloc.2
   IL_001e:  ldloc.2
   IL_001f:  brtrue.s   IL_002e
   IL_0021:  nop
   IL_0022:  ldstr      "dddd"
   IL_0027:  call       void [mscorlib]System.Console::WriteLine(string)
   IL_002c:  nop
   IL_002d:  nop
   IL_002e:  ldloc.1
   IL_002f:  ldloc.1
   IL_0030:  or
   IL_0031:  call       void [mscorlib]System.Console::WriteLine(int32)
   IL_0036:  nop
   IL_0037:  call       int32 [mscorlib]System.Console::Read()
   IL_003c:  pop
   IL_003d:  ret
    } // end of method Program::Main

saat kamu menggunakan || untuk menguji "a == null" dan "a.ToString () ==" sdffd ", IL akan

 .method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       63 (0x3f)
  .maxstack  2
  .locals init ([0] object a,
           [1] int32 b,
           [2] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  ldnull
  IL_0002:  stloc.0
  IL_0003:  ldc.i4.3
  IL_0004:  stloc.1
  IL_0005:  ldloc.0
  IL_0006:  brfalse.s  IL_001d
  IL_0008:  ldloc.0
  IL_0009:  callvirt   instance string [mscorlib]System.Object::ToString()
  IL_000e:  ldstr      "sdffd"
  IL_0013:  call       bool [mscorlib]System.String::op_Equality(string,
                                                                 string)
  IL_0018:  ldc.i4.0
  IL_0019:  ceq
  IL_001b:  br.s       IL_001e
  IL_001d:  ldc.i4.0
  IL_001e:  stloc.2
  IL_001f:  ldloc.2
  IL_0020:  brtrue.s   IL_002f
  IL_0022:  nop
  IL_0023:  ldstr      "dddd"
  IL_0028:  call       void [mscorlib]System.Console::WriteLine(string)
  IL_002d:  nop
  IL_002e:  nop
  IL_002f:  ldloc.1
  IL_0030:  ldloc.1
  IL_0031:  or
  IL_0032:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_0037:  nop
  IL_0038:  call       int32 [mscorlib]System.Console::Read()
  IL_003d:  pop
  IL_003e:  ret
} // end of method Program::Main

Sekarang Anda dapat melihat perbedaannya, tolong jangan pikirkan '|' atau 'dan' sebagai operator bersyarat, itu hanya operator logis, saya rasa tidak perlu menggunakannya untuk menilai kondisi

FrankX
sumber
2
The '|' or '&' is logical operator, in C #, it always treat as bit operator. Saya percaya akan hal ini juga, sampai saya melihat referensi ini, msdn.microsoft.com/en-us/library/kxszd0kx.aspx
user3207158
Jawaban Anda di luar konteks. Pertanyaannya tidak berkaitan dengan C # melainkan ke VB di mana empat operator logika: AndAlso, Or, OrElse, Not, dan Xor keduanya, operator logis dan Bitwise.
Jean-François
0

Kecuali logika kode Anda memerlukan perilaku hubungan arus pendek yang disediakan OrElse, saya akan cenderung menggunakan operator Or karena:

  • Menggunakan "Atau" itu sederhana dan hanya perlu sedikit mengetik.
  • Penghematan waktu komputasi menggunakan OrElse dapat diabaikan dalam banyak kasus.
  • Yang terpenting, menggunakan OrElse dapat menyembunyikan kesalahan di klausa selanjutnya yang mungkin tidak terungkap pada awalnya hingga kondisi tersebut pada akhirnya akan dipenuhi oleh logika program.
KnowKnot
sumber
0

Alasan kompilasi gagal dalam contoh adalah urutan operasi.

Pengurai ekspresi mencoba mengevaluasi "dbnull.value atau temp" terlebih dahulu.

if temp is (dbnull.value or temp) = 0

Kesalahannya ada di sini, karena Anda tidak dapat melakukan bitwise OR antara integer (temp) dan dbnull.value.

OrElse memperbaiki ini, bukan karena hubung singkatnya, tetapi karena urutan operasinya lebih rendah , sehingga "temp is dbnull.value" dan "3 = 0" sedang dievaluasi terlebih dahulu, daripada parser yang mencoba membandingkan dbNull dan suhu

Jadi evaluasi dengan OrElse berfungsi seperti yang Anda harapkan: (asumsikan temp = 3)

if temp is dbnull.value OrElse temp = 0 then
if 3 is dbnull.value OrElse 3 = 0 then
if false OrElse 3=0 then
if false OrElse false then
if false then

Ini sebenarnya adalah ujian masuk di perusahaan perangkat lunak tempat saya dulu bekerja, dan itu adalah masalah umum yang biasa saya temui di VB6. Jadi, sebaiknya beri tanda kurung pada sub-ekspresi Anda saat menggunakan operator boolean:

Ini akan dikompilasi dengan benar:

if (temp is dbnull.value) Or (temp = 0) then 

Meskipun, seperti yang telah ditunjukkan oleh semua orang, OrElse dan AndAlso sebenarnya adalah operator yang tepat untuk digunakan dalam konteks ini.

TomXP411
sumber