Kompilowanie i wykonywanie wyrażeń
Przekształcaj drzewa wyrażeń w delegaty możliwe do uruchomienia.
Kompilowanie i wykonywanie wyrażeń to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C# Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C# Academy zawiera 4 lekcji w sumie.
Od drzewa do delegata
Drzewo wyrażeń pozostaje danymi, dopóki nie zostanie skompilowane. Expression<TDelegate>.Compile() przekształca drzewo w rzeczywisty delegat, który można wywoływać.
using System;
using System.Linq.Expressions;
Expression<Func<int, int>> tree = x => x + 1;
Func<int, int> fn = tree.Compile();
Console.WriteLine(fn(5)); // 6Kompilowanie ręcznie zbudowanego drzewa
Drzewa zbudowane ręcznie kompiluje się w ten sam sposób, uzyskując działający delegat.
using System;
using System.Linq.Expressions;
var x = Expression.Parameter(typeof(int), "x");
var body = Expression.Multiply(x, Expression.Constant(3));
var lambda = Expression.Lambda<Func<int, int>>(body, x);
var fn = lambda.Compile();
Console.WriteLine(fn(4)); // 12Wywoływanie wyniku
Skompilowany delegat zachowuje się jak każdy inny: można go wywołać, przechować i przekazywać dalej.
using System;
using System.Linq.Expressions;
Expression<Func<int, int, int>> addExpr = (a, b) => a + b;
var add = addExpr.Compile();
Console.WriteLine(add(2, 3)); // 5
Console.WriteLine(add(10, 20)); // 30Kompilacja nie jest bezpłatna
Kompilacja wiąże się z kosztem w czasie wykonywania, dlatego należy buforować wynikowy delegat i używać go ponownie zamiast kompilować drzewo przy każdym wywołaniu.
using System;
using System.Linq.Expressions;
Expression<Func<int, int>> tree = x => x * x;
var square = tree.Compile(); // compile once
for (int i = 1; i <= 3; i++)
Console.Write(square(i) + " "); // 1 4 9
Console.WriteLine();Dynamiczne budowanie predykatów
Częstym zastosowaniem jest budowanie predykatów filtrujących w czasie wykonywania na podstawie danych wejściowych użytkownika, a następnie kompilowanie ich do obiektu Func.
using System;
using System.Linq.Expressions;
var n = Expression.Parameter(typeof(int), "n");
var isPositive = Expression.GreaterThan(n, Expression.Constant(0));
var pred = Expression.Lambda<Func<int, bool>>(isPositive, n).Compile();
Console.WriteLine(pred(5)); // True
Console.WriteLine(pred(-2)); // FalseŁączenie warunków
Przed kompilacją można łączyć predykaty za pomocą Expression.AndAlso / OrElse.
using System;
using System.Linq.Expressions;
var n = Expression.Parameter(typeof(int), "n");
var inRange = Expression.AndAlso(
Expression.GreaterThanOrEqual(n, Expression.Constant(1)),
Expression.LessThanOrEqual(n, Expression.Constant(10)));
var fn = Expression.Lambda<Func<int, bool>>(inRange, n).Compile();
Console.WriteLine(fn(5) + " " + fn(11)); // True FalseKompilowanie obliczeń
W czasie wykonywania można składać formuły arytmetyczne, co przydaje się w silnikach reguł i kalkulatorach.
using System;
using System.Linq.Expressions;
var p = Expression.Parameter(typeof(double), "p");
// price * 1.2 (add 20% tax)
var withTax = Expression.Multiply(p, Expression.Constant(1.2));
var calc = Expression.Lambda<Func<double, double>>(withTax, p).Compile();
Console.WriteLine(calc(100)); // 120DynamicInvoke dla lambd bez określonego typu
Jeśli użyto niegenerycznej metody Expression.Lambda, należy skompilować ją do obiektu Delegate i wywołać metodę DynamicInvoke.
using System;
using System.Linq.Expressions;
var x = Expression.Parameter(typeof(int), "x");
var body = Expression.Add(x, Expression.Constant(10));
Delegate d = Expression.Lambda(body, x).Compile();
Console.WriteLine(d.DynamicInvoke(5)); // 15Uwaga dotycząca wydajności
Po jednorazowej kompilacji skompilowane wyrażenie działa z wydajnością zbliżoną do delegata. W często wykonywanych ścieżkach należy skompilować je raz podczas uruchamiania i przechować delegata.
using System;
using System.Linq.Expressions;
Expression<Func<int, int>> tree = x => x + x;
var doubler = tree.Compile();
int total = 0;
for (int i = 0; i < 5; i++) total += doubler(i);
Console.WriteLine(total); // 0+2+4+6+8 = 20Błędy ujawniają się podczas kompilacji
Jeśli drzewo jest nieprawidłowe, na przykład brakuje w nim parametru, metoda Compile() zgłasza wyjątek. Dlatego przed użyciem drzew należy je zweryfikować.
using System;
using System.Linq.Expressions;
var x = Expression.Parameter(typeof(int), "x");
var y = Expression.Parameter(typeof(int), "y");
try {
// body references y but lambda only declares x
var lambda = Expression.Lambda<Func<int, int>>(Expression.Add(x, y), x);
lambda.Compile();
} catch (InvalidOperationException) {
Console.WriteLine("unbound parameter");
}Zastosowanie w praktyce
Zbuduj, skompiluj i uruchom małą formułę w jednym przebiegu.
using System;
using System.Linq.Expressions;
var x = Expression.Parameter(typeof(int), "x");
var formula = Expression.Add(
Expression.Multiply(x, Expression.Constant(2)),
Expression.Constant(3)); // 2x + 3
var fn = Expression.Lambda<Func<int, int>>(formula, x).Compile();
Console.WriteLine(fn(4)); // 11Szybkie sprawdzenie
Proszę sprawdzić, jak wykonywać drzewo wyrażeń.
Podsumowanie
Poznano sposób kompilowania i wykonywania drzew wyrażeń.
Compile()przekształca drzewo w delegata, którego można wywołać.- Należy buforować delegata, ponieważ kompilacja wiąże się z jednorazowym kosztem.
- Predykaty i formuły można budować dynamicznie, a następnie kompilować.
- Nieprawidłowe drzewa powodują wyjątek podczas wywołania
Compile().
Często zadawane pytania
Czy lekcja „Kompilowanie i wykonywanie wyrażeń” jest bezpłatna?
Tak — pełny tekst „Kompilowanie i wykonywanie wyrażeń” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C# Academy, przejdź na CoddyKit PRO. Kurs C# Academy zawiera 4 lekcji w sumie.
Co nauczysz się w „Kompilowanie i wykonywanie wyrażeń”?
Przekształcaj drzewa wyrażeń w delegaty możliwe do uruchomienia. Ćwiczysz C# Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć C# Academy?
Nie wymagamy żadnego doświadczenia. C# Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.
Ile czasu zajmuje lekcja „Kompilowanie i wykonywanie wyrażeń”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji C# Academy?
Tak. Każda lekcja C# Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Czym są drzewa wyrażeń
- Ręczne tworzenie wyrażeń
- Kompilowanie i wykonywanie wyrażeń
- Drzewa wyrażeń w dostawcach LINQ