0Pricing
C# Academy · Lekcja

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)); // 6

Kompilowanie 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)); // 12

Wywoł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)); // 30

Kompilacja 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 False

Kompilowanie 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)); // 120

DynamicInvoke 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)); // 15

Uwaga 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 = 20

Błę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)); // 11

Szybkie 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

  1. Czym są drzewa wyrażeń
  2. Ręczne tworzenie wyrażeń
  3. Kompilowanie i wykonywanie wyrażeń
  4. Drzewa wyrażeń w dostawcach LINQ
← Powrót do C# Academy