2009-06-23 9 views
7

Znalazłem coś bardzo dziwnego (chyba!). Jeśli spróbuję umieścić punkt przerwania w metodzie yes(), to nigdy nie wstrzyma programu podczas wykonywania funkcji. Jeśli spróbuję zrobić to samo z każdą inną linią kodu, będzie działać tak, jak powinien. Czy to błąd, czy jest coś, co mi ucieka?Debugger nie trafił w pułapkę

Filtr zwróci 2 obiekty, wszystko wydaje się działać zgodnie z oczekiwaniami, z wyjątkiem debuggera.

private void Form1_Load(object sender, EventArgs e) { 
    List<LOL> list = new List<LOL>(); 
    list.Add(new LOL()); 
    list.Add(new LOL()); 

    IEnumerable<LOL> filter = list.Where(
     delegate(LOL lol) { 
      return lol.yes(); 
     } 
    ); 

    string l = ""; <------this is hit by the debugger 
} 

class LOL { 
    public bool yes() { 
     bool ret = true; <---------this is NOT hit by the debugger 
     return ret; 
    } 
} 
+3

Zapamiętaj wynik metody zapytania, np. Gdzie jest _an obiekt reprezentujący zapytanie_. Nie jest to _ wynikami zapytania. To jest zapytanie. Dopóki nie powiesz "hej zapytanie, jakie są twoje wyniki?" że kwerenda faktycznie jest wykonywana. –

+1

Możesz teraz odpowiedzieć na tę małą zagadkę: Problem: http://blogs.msdn.com/ericlippert/archive/2007/09/05/psychic-debugging-part-one.aspx Rozwiązanie: http: //blogs.msdn. com/ericlippert/archive/2007/09/06/psychic-debugging-part-two.aspx –

Odpowiedz

16

Enumerable.Where jest operatorem leniwy - aż zadzwonisz coś, co przechodzi przez IEnumerable zwrócony przez gdzie (tj. Wywołanie .ToList() na nim), czynność nie zostanie wywołana.

Spróbuj zmienić swój kod do tego i sprawdzić, czy to jest wywoływana:

.... 
IEnumerable<LOL> filter = list.Where(
    delegate(LOL lol) { 
     return lol.yes(); 
    } 
).ToList(); 

string l = ""; 
2

Trzeba zmaterializować listę. Dodaj ...

filter.ToList(); 

... po złożeniu deklaracji, a trafisz w punkt przerwania. O najlepszej dyskusji, jaką widziałem na ten temat, jest here. Czyni leniwą ocenę, o wiele lepiej, niż ja mogłem.

2

Jak powiedzieli inni, właśnie określiłeś kryteria, ale nie poprosiłeś o ich wykonanie. To się nazywa leniwe ładowanie (chłopaki, poprawcie mnie, jeśli się mylę).

Uruchom pętlę foreach na filtrze, aby zobaczyć, co się stanie.

2

Jonathan ma rację.

Spróbuj uruchomić tę aplikację konsolową i ustaw punkty przerwania tam, gdzie jest to wskazane, aby widzieć ją wyraźnie.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      List<LOL> list = new List<LOL>(); 
      list.Add(new LOL()); 
      list.Add(new LOL()); 

      IEnumerable<LOL> filter = list.Where(
       delegate(LOL lol) 
       { 
        return lol.yes(); 
       } 
      ); 

      // Breakpoint #2 will not have been yet. 
      Console.Write("No Breakpoint"); // Breakpoint #1 
      // (Breakpoint #2 will now be hit.) 
      Console.Write("Breakpoint! " + filter.Count()); 
     } 

     class LOL 
     { 
      public bool yes() 
      { 
       bool ret = true; // Breakpoint #2 
       return ret; 
      } 

     } 

    } 
}