Nie każdy początkujący programista, który zaczyna swoją przygodę z platformą .NET jest świadomy działania mechanizmów zawartych w technologi którą poznaję. Dobrym przykładem może być tu tworzenie zapytań za pomocą LINQ i Deferred Execution (opuźnione wywołanie). No ale co to oznacza, a no mniej więcej tyle , że zapytania tworzone za pomocą LINQ nie są automatycznie wykonywane podczas ich tworzenia. Wykonanie zapytania jest odłożone w czasie. Aby to wszystko lepiej zrozumieć przejdźmy do przykładu:
[csharp]
int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var result = from n in numbers where n < 5 select n;
numbers[0] = -5;
foreach (var i in result)
{
Console.Write("{0},", i);
}
[/csharp]
Resultat powyższego kody to ciąg liczb: -5,4,1,3,2,0. Zatem jak widać po utworzeniu zapytania nie zostało ono wykonane. Wywołanie zapytania miało miejsce dopiero podczas użycia pętli foreach i element który zmieniliśmy został uwzględniony w końcowym zbiorze.
Skoro już wiemy, że wykonanie zapytania stworzonego za pomocą LINQ nie jest automatycznie wykonywane to pewnie chcieli byście wiedzieć co zrobić żeby od razu dostać dane które chcemy. Odpowiedź jest dość prosta, wystarczy po utworzeniu zapytania wywołać metodę która zwróci nam końcowy zbiór elementów np. ToList, ToArray.
[csharp]int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var result = (from n in numbers where n < 5 select n).ToList();
numbers[0] = -5;
foreach (var i in result)
{
Console.Write("{0},", i);
}
Console.WriteLine();[/csharp]
Wykonanie już takiego kody zwróci nam następujące liczby: 4,1,3,2,0.
Z Deferred Execution w LINQ wiąże się też jedna użyteczna funkcjonalność, a mianowicie możliwość ponownego użycia stworzonego zapytania. Dzięki temu tworzymy zapytanie raz i wykonujemy je dowolną ilość razy na zmodyfikowanym zbiorze.
[csharp]int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var result = from n in numbers where n <= 8 select n;
Console.WriteLine("Result count: {0}",result.Count());
numbers[0] = 11;
Console.WriteLine("Result count (after data changes): {0}", result.Count());
Console.WriteLine("First run");
foreach (var i in result)
{
Console.Write("{0},", i);
}
Console.WriteLine();
for (int i = 0; i < numbers.Length; ++i)
{
numbers[i] = -numbers[i];
}
Console.WriteLine("Second run (after data changes)");
foreach (var i in result)
{
Console.Write("{0},", i);
}
Console.WriteLine();
[/csharp]
Rezultat wykonania powyższego kody będzie następujący:
Result count: 9 Result count (after data changes): 8 First run 4,1,3,8,6,7,2,0, Second run (after data changes) -11,-4,-1,-3,-9,-8,-6,-7,-2,0,
Świadomość istnienia mechanizmów takich jak Deferred Execution w LINQ jest bardzo ważna, gdyż taka wiedza uchroni nas przed błędami, których wykrycie staje się bardzo ciężkie. Tak więc podsumowując warto zagłębiać się w tajniki technologi aby świadomie używać tego co oferuje nam dana technologia.
Przykładowy program można pobrać klikając na poniższy link:[dm]3[/dm]