Neden bir kısa devre VEYA hem de C # operatörünün kısa devre varyasyon var?


9

Periyodik olarak, bunu merak ediyorum:

Kısa devre VEYA her zaman kısa devre yapmamış VEYA operatörünün verdiği değeri döndürür mü?

Kısa devre VEYA'nın her zaman daha hızlı değerlendirmesini bekliyorum. Peki, kısa devre dışı VEYA operatörü tutarlılık için C # dilinde dahil edildi mi?

Neyi kaçırdım?


9
Aynı dönüş değeri - evet. Aynı yan etkiler - hayır.
Meslek

2
Diyelim ki f()bir istisna yaratıyor, düşünün true || f()ve true | f(). Farkı görüyor musunuz? İlk ifade değerlendirilir true, ikincisinin değerlendirilmesi bir istisna atılır.
scarfridge

Yanıtlar:


25

Her iki işlenen de, boole türü olmayan C'den gelen farklı şeyler içindir. Kısa devre versiyonu || kısa boole olmayan versiyonu ise sadece boolean ile çalışır | integral tiplerle çalışır, bitsel olarak veya. Sadece 0 veya 1 olmak üzere tek bir bit ile temsil edilen booleanlar için kısa devre olmayan bir mantıksal işlem olarak çalıştı.

http://en.wikibooks.org/wiki/C_Sharp_Programming/Operators#Logical


10
Bağlantı için +1. Bu soruyu okuduğumda "ne?" afaik'ten beri bunların resmi adı mantıklı ve bitseldir ya da nasıl çalıştıklarının yan etkileri olan kısa devre ve kısa devre değildir.
stijn

1
+1 "yalnızca boolean işlenenlerde çalışır" ifadesini
görüyorum

2
Kontrol etmek zorunda kaldım, ama aslında, |operatörün, iki boole değerine oruygulandığında, iki tamsayı değerine uygulandığında olduğu gibi CIL'de aynı operatöre derlendiği doğrudur - bir koşullu için ||CIL'de derlenenin aksine brtrueatlamak.
quentin-starin

13

|(bitsel-veya) gibi tipler için kısa devre olmamalıdır int. Çünkü hemen hemen tüm durumlarda |doğru sonucu hesaplamak için bir ifadenin her iki tarafını da hesaplamanız gerekir . Örneğin, sonucu 7 | f(x)nedir?

Eğer f(x)değerlendirilmez, sen söyleyemezsin.

Ayrıca, bu operatörü kısa devre olmadığı boolzaman için kısa devre yapmak tutarsız olacaktır int. Bu arada, |bilerek hiç mantıklı karşılaştırmalar için hiç kullanmadım , mantıklı |bir operatör olarak konuşmanın çok sakıncalı olduğunu düşünüyorum .

|| ancak kısa devre değerlendirmenin iyi çalıştığı mantıksal karşılaştırmalar içindir.

Aynı şey, bu operatörlerin kökeninin bulunduğu C ve C ++ için de geçerlidir.


5

Bu doğrudur, kısa devre VEYA operatörü (||) daima kısa devre olmayan VEYA operatörü (|) ile aynı değeri döndürür. (*)

Ancak, ilk işlenen doğruysa, kısa devre operatörü ikinci işlenenin değerlendirilmesine neden olmazken, kısa devre olmayan operatör her zaman her iki işlenenin de değerlendirilmesine neden olur. Bunun performans üzerinde ve bazen yan etkilerde etkisi olabilir.

Bu nedenle, her ikisi için de bir kullanım vardır: performansa önem veriyorsanız ve ikinci işlenenin değerlendirilmesi herhangi bir yan etki üretmezse (veya bunlarla ilgilenmiyorsanız), elbette kısa devre operatörünü kullanın . Ancak, herhangi bir nedenle ikinci işlenenin yan etkilerine ihtiyacınız varsa, kısa devre dışı operatörü kullanmalısınız.

Kısa devre dışı operatörü kullanmanız gereken bir örnek:

if( write_customer_to_database() != SUCCESS |
    write_supplier_to_database() != SUCCESS |
    write_order_to_database() != SUCCESS )
{
    transaction_rollback();
}

(*) İlk işlenenin yanlış nedenlerle yan etki ile değerlendirilmesinin ikinci işlenenin yanlış yerine doğru olarak değerlendirildiği gerçekten sapkın senaryolar dışında.


2
+1 Ama bunu başarıyı veya başarısızlığı göstermek için işlevleri kullanmak dışında (örneğin örneğiniz gibi) eklemek istiyorum: yan etkileri olan işlevlerden genellikle kaçınılmalıdır ...
Marjan Venema

1
Evet, muhtemelen bu yüzden bugüne kadar kısa devre dışı operatörlerden hiçbirini kullanmadım ve şansım şimdiye kadar zayıf.
Mike Nakis

Bu örnek, katı soldan sağa sırada değerlendirilen işlenenlere bağlıdır. C # bunu garanti eder, ancak birçok benzer dil (C ve C ++ dahil) bunu garanti etmez.
Keith Thompson

Kısa devre değerlendirmesi bu örnek için anlamlı olmaz mıydı, çünkü bunlardan herhangi biri başarısız olursa tüm işlemler geri alınacak mı? (Aramaların anlambilimi hakkında bazı varsayımlar yapıyorum.)
Keith Thompson

@KeithThompson haklısın, kısa devre dışı değerlendirme gereksiz işlemeye neden olur ve bu anlamda örnek biraz topaldır, ancak değişmeyi garanti etmek kadar sakıncalı değildir, çünkü gerçek şu ki kısa devre değerlendirmesinde kalır write_customer_to_database () başarılı olursa, yazma _... işlevlerinin geri kalanı hiçbir zaman çağrılmaz ve başarısızlık durumunda bazı gereksiz işlemleri gerçekleştirmekten daha başarılı olması durumunda daha iyi çalışır.
Mike Nakis

4

Kısa devre olmayan varyantı kullanmak için 2 neden olacaktır:

  1. yan etkileri korumak (ancak geçici bir değişkenle kodlamak daha açıktır)

  2. kısa devrede çataldan kaçınarak zamanlama saldırılarını önleyin (bu, ikinci işlenen bir değişkense, ancak derleyicinin yine de yapabileceği bir mikro optimizasyon ise çalışma zamanı verimliliğini artırabilir)


Sağlanan tek doğru sebep budur, bunun neden en yüksek
oylarla

2

operatörün sağ tarafının yan etkisi varsa ve programcı, dönüş değerlerini kontrol etmeden önce her iki yan etkinin de olmasını istemeyi amaçladıysa.


5
Eek. Lütfen böyle kod yazmayın… yan etkilere güveniyorsanız, iki farklı ifadeniz varsa, sonuçları atayın ve daha sonra test edin .
Konrad Rudolph
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.