Veya OrElse'e karşı


96

Arasındaki fark nedir ya ve OrElse ?

if temp is dbnull.value or temp = 0

şu hatayı üretir:

Operatör '=', 'DBNull' türü ve 'Tamsayı' türü için tanımlanmadı.

bu bir cazibe gibi çalışırken !?

if temp is dbnull.value OrElse temp = 0

Yanıtlar:


147

OrElseBir olan kısa devre operatör Ordeğil.

Boolean 'veya' operatörünün tanımına göre, ilk terim Doğru ise bütün kesinlikle doğrudur - bu nedenle ikinci terimi değerlendirmemize gerek yoktur.

OrElseBu biliyor, bu yüzden denemek ve değerlendirmek değil temp = 0o kurulmuş oluyor keztemp Is DBNull.Value

Orbunu bilmiyor ve her zaman her iki terimi de değerlendirmeye çalışacak. Ne zaman temp Is DBNull.Value, sıfırla karşılaştırılamaz, bu yüzden düşer.

Kullanmalısınız ... iyi, hangisi mantıklıysa.


2
Öyleyse veya yalnızca kodumun bağlı olduğu yan etkilere sahip veya sonra bir işlevi çağırdığımda mantıklı olur?
Ralph M. Rickenbach

4
Veya ilki doğruysa, ikinci öğenin hatayı tetiklemediği her durumda mantıklı ...
hayranlıkla

4
@ malach: Sanırım öyle (diğer birçok dilde OrElse davranışını gerçekten varsayılan olarak alıyorsunuz): Bileşik koşullu işlevlerde yan etkileri olan işlevleri çağırmak iyi bir fikir değildir, bu da kodu okunamaz hale getirir.
Utaal

4
@ awe: evet, ama neden tanımı gereği ifadenin sonucunu değiştirmeyecek bir şeyi değerlendirerek zaman harcamak istiyorsunuz?
Utaal

3
@MarkJ: Fazladan dört karakterin okunabilirliği bozduğunu gerçekten düşünmüyorum. Öte yandan, anlamlı olması için yan etkilerin varlığına (malach'ın yazdığı gibi) bağlı bir operatör kullanmak kulağa kötü bir fikir gibi geliyor (ve okunabilirliği zorlaştırabilir!). Böyle yerlerde yan etkileri büyük bir hayır-hayır olarak değerlendiririm ve "Or" yerine "OrElse" yi tercih edeceğim herhangi bir durum düşünemiyorum. Bu operatörlerin bu şekilde çalışması üzücü, çünkü "OrElse" davranışı muhtemelen "Or" kullanılırken bile (özellikle diğer dillerden geliyorsa) en çok beklenen şeydir.
Kjartan

43

Bu, herkesin Coditional Or (||) ve Koşullu Ve (&&) kullandığı C # ile aynı davranıştır, burada normal Or (|) ve normal And (&) da vardır. Dolayısıyla C # ile VB.Net'i karşılaştırmak:

| => Veya

|| => OrElse

& => Ve

&& => VeAyrıca

Koşullu mantıksal işleçler çok kullanışlıdır, eğer yapıların iç içe geçmesini engeller. Ancak bazen her iki kod yolunun da isabetli olmasını sağlamak için normal boole operatörlerine ihtiyaç duyulur.


9
Bunun mevcut olduğunu asla bilmiyordum. Yeni bilgiler için teşekkürler. "|" Kullanmak isteyeceğim herhangi bir durumu gerçekten göremesem de bilmek güzel. Sanırım ikinci koşulun yan etkilerin herhangi bir anlam ifade etmesine neden olması gerekir ve bu kendi başına bana göre pek mantıklı değil! ;)
Kjartan

8
Eh, bildiğim kadarıyla |ve &C # 'da bitsel operatörler, boole işlemleri değil.
Nyerguds

8

OrElse kısa devre yapıyor , bu, ilk taraf bir eşleşme ise ifadenin yalnızca bir tarafının test edileceği anlamına gelir.

Tıpkı AndAlso gibi, ilk yarısı başarısız olursa ifadenin sadece bir tarafını test edecektir.


4

(Diğer cevaplara baktım ve çok hatalı olduğumu fark ettim)

OrElse operatörü "iki ifade üzerinde kısa devre yapan mantıksal ayırma gerçekleştirir", yani: eğer sol işlenen doğruysa ve bu nedenle tüm ifadenin doğru olması garanti edilirse, sağ işlenen bile değerlendirilmez (bu, gibi durumlar:

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

sağ taraftaki işlenen tarafından bir NullReferenceException atmasından kaçınmak için.

Umarım bu (yani şaşırttı değilim tembel değerlendirme ) varsayılan davranış değildir orve andbu C / C ++ olduğu gibi C # (ve diğer birçok dil ...)


7
Mesele şu ki, VB classic'te, kısa devre olmayan sadece And ve Or vardı. VB.NET'in ilk betalarının aslında bu operatörlerin davranışlarını değiştirdiğini söylemekte haklı olduğumu düşünüyorum - kargaşa çıktı, bu yüzden geri değiştirildiler ve AndAlso ve OrElse (kısa devre) tanıtıldı. En iyileri bunlar olsaydı, düşünmeleri gereken alternatif isimleri ancak hayal edebiliyorum ...
AakashM

1
Or ve OrElse (| ve || in C #) sağlayarak bu, geliştiricinin kendi kodlarını nasıl işleyeceğini seçmesine olanak tanır. Yukarıdaki kodu kullanarak, a değişkenindeki boş bir değeri işlemek için bir deneme yakalama kullanmam gerekir. OrElse, geliştiricinin bunu if ifadesinin diğer kısmında bir istisna yerine bilinen olası bir sonuç olarak ele almasına izin verir. Eğer a değişkeni, değişkene bir değer atandığında (yani yöntemin dışında) daha az kontrole sahip olduğunuz bir yöntemde bir parametre ise bu daha açıktır
Kevin Hogg

Kısa devre, OR ve VE'nin varsayılan davranışı değildir ve c # 'da da. c #, bitsel ve mantıksal / kısa devre işlemleri için iki farklı operatöre sahiptir. && ve || mantıksal karşılaştırmalar gerçekleştirin ve bir boole değeri döndürür. operatörler bitseldir ve bir tamsayı değeri döndürür. O halde 1 || 2 "true" değerini döndürür, 1 | 2, "3" değerini döndürür.
TomXP411

4

OrElse ilk ifadeyi değerlendirdikten sonra eğer doğruysa ifadeye ilerlerken OR ifadelerine geçmeden önce iki ifadeyi değerlendirir.

Misal:

Textbox1.Text= 4

Textbox2.Text= ""

OrElse Kullanımı

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

Sonuç: DOĞRU


OR kullanma

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

            MsgBox("True")
  End If

Sonuç: Dize ikiye dönüştürülemez hata.


3

Bert'in cevabı pek doğru değil. '|' veya '&' mantıksal operatördür, C # 'da her zaman bit operatörü olarak davranır, lütfen örnek olarak aşağıdaki koda bakın

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

Aşağıdaki 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

|| kullandığınızda "a == null" ve "a.ToString () ==" sdffd "yi test etmek için IL,

 .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

Şimdi farkı görebilirsiniz, lütfen '|' veya 've' koşullu operatör olarak, sadece mantıksal bir operatör, koşulu yargılamak için kullanmanın gerekli olduğunu düşünmüyorum


2
The '|' or '&' is logical operator, in C #, it always treat as bit operator. Buna ben de inandım, bu referansı görene kadar, msdn.microsoft.com/en-us/library/kxszd0kx.aspx
user3207158

Cevabınız bağlam dışı. Soru C # ile değil, dört mantıksal operatörün bulunduğu VB ile ilgilidir: And, AndAlso, Or, OrElse, Not ve Xor, hem mantıksal hem de Bitwise operatörleri.
Jean-François

0

Kod mantığınız OrElse'nin sağladığı kısa devre davranışını gerektirmedikçe, Or operatörünü kullanmaya eğilimliyim çünkü:

  • "Veya" kullanmak basittir ve daha az yazı gerektirir.
  • OrElse kullanmanın hesaplamalı zaman tasarrufu çoğu durumda ihmal edilebilir düzeydedir.
  • En önemlisi, OrElse kullanımı, daha sonraki cümlelerde bulunan ve bu koşullar sonunda program mantığı tarafından karşılanana kadar başlangıçta ortaya çıkmayabilecek hataları gizleyebilir.

0

Örnekte derlemenin başarısız olmasının nedeni işlemlerin sırasıdır.

İfade ayrıştırıcısı önce "dbnull.value veya temp" değerini değerlendirmeye çalışıyor.

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

Hata burada, çünkü bir tamsayı (temp) ile dbnull.value arasında bit düzeyinde VEYA yapamazsınız.

OrElse, kısa devre olduğu için değil, işlem sırasına göre daha düşük olduğu için bunu düzeltir . düzeltir ve bu nedenle dbNull ile karşılaştırmaya çalışan ayrıştırıcı yerine ilk önce "temp dbnull.value" ve "3 = 0" değerlendirilir. temp.

Yani OrElse ile değerlendirme beklediğiniz gibi çalışır: (temp = 3 varsayınız)

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

Bu aslında eskiden çalıştığım bir yazılım şirketinde bir giriş sınavındaydı ve VB6'da karşılaştığım yaygın bir sorundu. Bu nedenle, boole operatörlerini kullanırken alt ifadelerinizi parantez içine almak iyi bir fikirdir:

Bu doğru bir şekilde derlenmiş olurdu:

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

Yine de, herkesin daha önce işaret ettiği gibi, OrElse ve AndAlso, bu bağlamda kullanılacak gerçekten doğru operatörlerdir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.