5

W języku C# jest zagwarantowane, że wyrażenia są oceniane od lewej do prawej?Ocena wyrażeń od lewej do prawej

Na przykład:

myClass = GetClass(); 
if (myClass == null || myClass.Property > 0) 
    continue; 

Czy istnieją języki, które nie spełniają?

Odpowiedz

14

rzeczywiście odnoszą się do cech języka zwanego „zwierania wyrażeń logicznych”:

Oznacza to w ten sposób: Gdy wynik logicznej wypowiedzi nie może już zmienić, na przykład kiedy jest jasne, że wyrażenie będzie oceniać jako "prawda" lub "fałsz" bez względu na to, pozostałe części wyrażenia nie będą oceniane.

Na przykład C#, Java lub JavaScript to robią i można na nich polegać w tych językach (aby odpowiedzieć na pytanie).

W twoim przypadku, jeśli MojaKlasa nie jest zerowy:

  • MyClass == null FALSE
  • ponieważ jest to „lub” ekspresja, druga część nadal może zmienić wynik, więc jest ona oceniana
  • myClass.Property > 0 określa końcowy wynik

jeśli MojaKlasa jest zerowy:

  • MyClass == null wartość true
  • ponieważ jest to „lub” ekspresja, to nie ma znaczenia, co następuje
  • nie więcej ewaluacja jest zrobione, końcowy wynik jest prawdziwy

Istnieją języki, które robią brak wyrażeń logicznych zwarcia. Klasyczna VB jest przykładem, tutaj "myClass.Property> 0" byłaby oceniana i powodowałaby błąd, gdyby MyClass był zerowy (nazywany "Nothing" w VB).

0

Kolejność oceny zależy od operatora, w tym przypadku wartość boolowska lub (||) jest zdefiniowana jako zwykle nazywana short-circuiting, aby tworzyć konstrukcje takie jak ta.

5

Zwarcie jest opisana w rozdziale 7.11 C# 3.0 specyfikacji:

operacja X || y odpowiada operacji x | y, z wyjątkiem tego, że y jest oceniane tylko wtedy, gdy x nie jest prawdą.

Tak, wszystko w porządku.

Podobnie jak w przypadku innych języków - nigdy nie lubię mówić w przypadku języków wszystkich języków. W VB.NET można używać OrElse i AndAlso, które są zwarte, ale proste lub nie.

2

Ale uważaj:

jeśli masz coś

sprintf (buf, "% s% s", func1 (& var), func2 (& var));

z efektami ubocznymi na var, nie jest zdefiniowany (w C, nie jestem pewien, czy kolejność oceny jest zdefiniowana w innych językach), w którym kolejności wykonywane są func1() i func2() (zależy to od tego, w którym kolejność (lewy lub prawy) argumenty są umieszczane na stosie i oceniane stamtąd.

+0

W języku C# określona jest dokładna kolejność. – Martijn

0

nie jestem pewien, czy naprawdę jesteś zainteresowany lub w celu oceny zwarcia?

nie jestem 100 % oczywiście, ale o ile wiem, kolejność oceny będzie zawsze taka sama w języku C# (i zakładam, że większość, jeśli nie wszystkie języki .net). Ocena zwarcia działa tak, jak wyjaśniono w poprzednich odpowiedziach:

Jednak w języku C# można wybrać zwarcie za pomocą prostych operatorów (& zamiast & &). Normalnie chcesz zwarcie, ale może to być przypadek, w którym chcesz wykonać wszystkie oceny.

0

Operatory i języki w językach takich jak Ada, Visual Basic i Pascal nie ulegają zwarciu. Zapewniają one dodatkowe operatory, aby umożliwić tę funkcjonalność, np. "A potem" i "albo inaczej" w Adzie.

0

Python ma zwarcia or i and operatorów.

0

W języku Java i Haskell & & i || także zwarcie.

Ciekawostka: w Haskell przychodzi to naturalnie z językiem (możesz zdefiniować własne operatory, które to robią), podczas gdy w Javie i C# jest to specyficzne dla dla tych dwóch operatorów.

0

Właściwie to spięcie jest częścią, ale trzeba również wiedzieć, czy język gwarantuje ich ocenę od lewej do prawej. Na przykład C (ANSI, ISO, C99) NIE gwarantuje oceny od lewej do prawej. W przykładowym kodzie byłoby możliwe sprawdzenie wartości Property przed sprawdzeniem dla NULL lub wykonanie obu jednocześnie ... większość kompilatorów tego nie robi, ale nic nie uniemożliwia tego i jest w pełni zgodne ze specyfikacją. Mówi nawet, aby NIE pisać takiego kodu z tego powodu.

Powiązane problemy