İfade ağaçları (C#)

İfade ağaçları, her düğümün bir ifade olduğu, örneğin bir yöntem çağrısı veya gibi x < y bir ikili işlem olduğu ağaç benzeri bir veri yapısında kodu temsil eder.

İfade ağaçları ile temsil edilen kodu derleyebilir ve çalıştırabilirsiniz. Bu, yürütülebilir kodun dinamik olarak değiştirilmesini, çeşitli veritabanlarındaki LINQ sorgularının yürütülmesini ve dinamik sorguların oluşturulmasını mümkün bir şekilde sunar. LINQ içindeki ifade ağaçları hakkında daha fazla bilgi için bkz. dinamik sorgular oluşturmak için ifade ağaçları kullanma (C#).

İfade ağaçları ayrıca dinamik diller ve .NET arasında birlikte çalışabilirlik sağlamak ve derleyici yazıcılarının Microsoft ara dili (MSIL) yerine ifade ağaçları sunmak için dinamik dil çalışma zamanı (DLR) içinde de kullanılır. DLR hakkında daha fazla bilgi için bkz. dinamik dil çalışma zamanına genel bakış.

C# veya Visual Basic derleyicisinin anonim lambda ifadesine göre sizin için bir ifade ağacı oluşturmasını sağlayabilir veya ad alanını kullanarak System.Linq.Expressions el ile ifade ağaçları oluşturabilirsiniz.

Lambda Ifadelerinden Ifade ağaçları oluşturma

Lambda ifadesi türünde Expression<TDelegate> bir değişkene atandığında, derleyici lambda ifadesini temsil eden bir ifade ağacı oluşturmak için kodu yayar.

C# derleyicisi yalnızca ifade lambdaları (veya tek satırlık Lambdalar) için ifade ağaçları oluşturabilir. İfade lambdaları (veya çok satırlı Lambdalar) ayrıştırılamaz. C# ' deki lambda ifadeleri hakkında daha fazla bilgi için bkz. lambda ifadeleri.

Aşağıdaki kod örnekleri, C# derleyicisinin lambda ifadesini num => num < 5 temsil eden bir ifade ağacının nasıl oluşturulduğunu gösterir.

Expression<Func<int, bool>> lambda = num => num < 5;  

API kullanarak Ifade ağaçları oluşturma

API kullanarak ifade ağaçları oluşturmak için sınıfını kullanın Expression . Bu sınıf, bir değişken veya parametre temsil eden veya MethodCallExpression bir yöntem çağrısını temsil eden belirli türlerin ParameterExpression ifade ağacı düğümlerini oluşturan statik fabrika yöntemleri içerir. ParameterExpression, MethodCallExpression ve diğer ifadeye özgü türler de ad alanında tanımlanmıştır System.Linq.Expressions . Bu türler soyut türden Expression türetilir.

Aşağıdaki kod örneğinde, API kullanarak lambda ifadesini num => num < 5 temsil eden bir ifade ağacının nasıl oluşturulacağı gösterilmektedir.

// Add the following using directive to your code file:  
// using System.Linq.Expressions;  
  
// Manually build the expression tree for
// the lambda expression num => num < 5.  
ParameterExpression numParam = Expression.Parameter(typeof(int), "num");  
ConstantExpression five = Expression.Constant(5, typeof(int));  
BinaryExpression numLessThanFive = Expression.LessThan(numParam, five);  
Expression<Func<int, bool>> lambda1 =  
    Expression.Lambda<Func<int, bool>>(  
        numLessThanFive,  
        new ParameterExpression[] { numParam });  

.NET Framework 4 veya sonraki sürümlerde, ifade ağaçları apı 'si, döngüleri, koşullu blokları ve try-catch blokları gibi atamaları ve denetim akışı ifadelerini de destekler. API 'yi kullanarak, C# derleyicisi tarafından lambda ifadelerinden oluşturulanlardan daha karmaşık ifade ağaçları oluşturabilirsiniz. Aşağıdaki örnek, bir sayının faktöriyelini hesaplayan bir ifade ağacının nasıl oluşturulacağını göstermektedir.

// Creating a parameter expression.  
ParameterExpression value = Expression.Parameter(typeof(int), "value");  
  
// Creating an expression to hold a local variable.
ParameterExpression result = Expression.Parameter(typeof(int), "result");  
  
// Creating a label to jump to from a loop.  
LabelTarget label = Expression.Label(typeof(int));  
  
// Creating a method body.  
BlockExpression block = Expression.Block(  
    // Adding a local variable.  
    new[] { result },  
    // Assigning a constant to a local variable: result = 1  
    Expression.Assign(result, Expression.Constant(1)),  
    // Adding a loop.  
        Expression.Loop(  
    // Adding a conditional block into the loop.  
           Expression.IfThenElse(  
    // Condition: value > 1  
               Expression.GreaterThan(value, Expression.Constant(1)),  
    // If true: result *= value --  
               Expression.MultiplyAssign(result,  
                   Expression.PostDecrementAssign(value)),  
    // If false, exit the loop and go to the label.  
               Expression.Break(label, result)  
           ),  
    // Label to jump to.  
       label  
    )  
);  
  
// Compile and execute an expression tree.  
int factorial = Expression.Lambda<Func<int, int>>(block, value).Compile()(5);  
  
Console.WriteLine(factorial);  
// Prints 120.  

daha fazla bilgi için, Visual Studio sonraki sürümleri için de geçerli olan Visual Studio 2010 ' de ifade ağaçları ile dinamik yöntemler üretmekonusuna bakın.

Ifade ağaçlarını ayrıştırma

Aşağıdaki kod örneği, lambda ifadesini num => num < 5 temsil eden ifade ağacının parçalar halinde nasıl birleştirilebileceğini gösterir.

// Add the following using directive to your code file:  
// using System.Linq.Expressions;  
  
// Create an expression tree.  
Expression<Func<int, bool>> exprTree = num => num < 5;  
  
// Decompose the expression tree.  
ParameterExpression param = (ParameterExpression)exprTree.Parameters[0];  
BinaryExpression operation = (BinaryExpression)exprTree.Body;  
ParameterExpression left = (ParameterExpression)operation.Left;  
ConstantExpression right = (ConstantExpression)operation.Right;  
  
Console.WriteLine("Decomposed expression: {0} => {1} {2} {3}",  
                  param.Name, left.Name, operation.NodeType, right.Value);  
  
// This code produces the following output:  
  
// Decomposed expression: num => num LessThan 5  

Ifade ağaçlarının dengeszlik düzeyini bilme

İfade ağaçları sabit olmalıdır. Yani, bir ifade ağacını değiştirmek istiyorsanız, var olan birini kopyalayarak ve içindeki düğümleri değiştirerek yeni bir ifade ağacı oluşturmanız gerekir. Varolan ifade ağacında çapraz geçiş yapmak için bir ifade ağacı Visitor kullanabilirsiniz. Daha fazla bilgi için bkz. ifade ağaçlarını değiştirme (C#).

Ifade ağaçlarını derleme

Expression<TDelegate>Türü, bir ifade ağacı tarafından temsil edilen kodu bir çalıştırılabilir temsilciye derlenen yöntemi sağlar Compile .

Aşağıdaki kod örneği, bir ifade ağacının nasıl derlendiğini ve sonuçta elde edilen kodu nasıl çalıştıracağınızı gösterir.

// Creating an expression tree.  
Expression<Func<int, bool>> expr = num => num < 5;  
  
// Compiling the expression tree into a delegate.  
Func<int, bool> result = expr.Compile();  
  
// Invoking the delegate and writing the result to the console.  
Console.WriteLine(result(4));  
  
// Prints True.  
  
// You can also use simplified syntax  
// to compile and run an expression tree.  
// The following line can replace two previous statements.  
Console.WriteLine(expr.Compile()(4));  
  
// Also prints True.  

Daha fazla bilgi için bkz. ifade ağaçlarını yürütme (C#).

Ayrıca bkz.