2010-02-22 18 views
13

To tylko pytanie "jestem ciekawy".C# - Jak utworzyć niewykrywalną nieskończoną pętlę?

w C# -in-Jon Skeet głębokości mówi o wyrażeniach lambda:
„jeśli istnieje nonvoid typ zwracany każda ścieżka kod musi zwrócić wartość zgodną” (strona 233)

Przypis potem mówi:
„Paths Code rzucanie wyjątki nie trzeba zwracać wartość, oczywiście, i tu nie wykrywalne pętle nieskończone”. (Strona 233)

Zastanawiam się, co stanowi niewykrywalną nieskończoną pętlę?

Czy można to zrobić tylko logicznie? lub odbywa się za pomocą czynników zewnętrznych, takich jak baza danych lub system plików?

+0

@JonSkeet może może wyjaśnić. –

Odpowiedz

21

Co Jon odnosi się to opisano w punkcie 8.1 specyfikacji. Kompilator może wykryć tylko bardzo proste pętle nieskończone, jak:

while(true) { if (0 != 0) return 123; } 

kompilator jest wystarczająco inteligentny, aby zobaczyć, że zwrot nie został osiągnięty, a zatem, że pętla jest nieskończona. To jest legalne, choć szalony, aby powiedzieć:

int M() { while(true) { } } 

bo chociaż nie ma ścieżki, która zwraca int, nie ma też droga, która zwraca bez powrocie int!

Kompilator nie jest wystarczająco inteligentny, aby znaleźć inne rodzaje nieskończonych pętli. Na przykład:

int x = 123; 
while(true) { if (x * 0 != 0) break; } 

Jest to wyraźnie nieskończona pętla. Ale kompilator tego nie wie. Kompilator mówi "cóż, być może istnieje pewna wartość x, gdzie x * 0 nie jest zerem, więc wtedy przerwa jest osiągalna, więc to nie jest nieskończona pętla". Ty i ja wiemy, że to niemożliwe, ponieważ znamy matematykę, ale kompilator nie.

Przeczytaj rozdział 8.1, jeśli chcesz poznać szczegóły.

+3

Naprawdę nie pamiętam, pisząc to - co sugeruje, że przypis wynika z twojego wpływu :) –

+2

@Jon: Pierwotnie napisałeś: "Wyrzucanie kodu wyjątków nie musi oczywiście zwracać wartości". Zauważyłem, że wykrywalne nieskończone pętle również liczą się jako nieosiągalne punkty końcowe. –

+2

Dobrze - to chyba bardziej szczegółowy poziom dla każdego z nas :) –

3

To dość trywialne, aby stworzyć nieskończoną pętlę wykorzystującą źródła zewnętrzne, a nawet nadużywać narzędzi, takich jak interfejsy.

Na przykład

public interface INumbers 
    { 
     int GetNumber(int arg); 
    } 
    public class StaticNumber : INumbers 
    { 
     public int GetNumber(int arg) 
     { 
      return 1; 
     } 
    } 
    public void DoStuff(INumbers num) 
    { 
     int i = 42; 
     while ((i = num.GetNumber(i)) != 0) 
     { 
      ; 
     } 
    } 

i prosty

Action action =() => DoStuff(new StaticNumber()); 
Powiązane problemy