簡體   English   中英

參數和變量如何在 C# 表達式樹中實際工作?

[英]How do parameters and variables actually work in C# Expression trees?

老實說,我只是迷路了,我似乎無法理解表達式樹語法應該如何應用於 function,並且在嘗試創建最簡單的 lambdas 時不斷出錯。

讓我們以一個非常基本的 function 為例:你提供一個數字作為參數,它只是將它添加到 0,是的,它沒用,但我什至無法讓它工作:

public void AddNumber(int number)
    {
        var input = Expression.Parameter(typeof(int), "number");
        var result = Expression.Variable(typeof(int), "result");
        
        var addAssign = Expression.AddAssign(result, input);

        int myExpectedResult = Expression.Lambda<Func<int, int>>(addAssign, input).Compile()(number);
    }

我收到一個錯誤,因為變量 result 已創建但未定義,這是有道理的。 所以我假設我需要為它分配一些值以使其工作:

public void AddNumber(int number)
    {
        var input = Expression.Parameter(typeof(int), "number");
        var result = Expression.Variable(typeof(int), "result");
        
        var addAssign = Expression.AddAssign(result, input);

        int myExpectedResult = Expression.Lambda<Func<int, int>>(addAssign, input).Compile()(number);
    }

同樣的錯誤,我假設是因為分配沒有真正被考慮在內,因為它沒有被使用。 但是您也不能將該分配變量用作 AddAssign function 的參數,因此它基本上沒有區別。

現在,如果我創建一個塊表達式來連續執行兩個賦值,這將消除錯誤,但是,我的“輸入”現在總是設置為 0:

        public void AddNumber(int number)
    {
        var input = Expression.Parameter(typeof(int), "number");
        var result = Expression.Variable(typeof(int), "result");

        var blockExpression = Expression.Block(new[] { input, result },
            Expression.Assign(result, Expression.Constant(0)),
            Expression.AddAssign(result, input));

        int myExpectedResult = Expression.Lambda<Func<int, int>>(blockExpression, input).Compile()(number);
    }

您實際上應該如何簡單地添加一個參數,創建一個變量,然后為該變量賦值以返回它? 我似乎找不到任何教程可以正確解釋如何在不同的 BlockExpressions 中保持參數/變量之間的鏈接。

非常感謝! 任何幫助表示贊賞!

你非常接近,但AddAssign+= ,所以你試圖做一些看起來像

x => x += y

其中y未定義且+=無法寫入x

而是嘗試對+使用Expression.Add ,對 integer 值使用Expression.Constant

像下面這樣的東西應該可以工作:

var paramExp = Expression.Parameter(typeof(int), "x");
var intExp = Expression.Constant(5);

// x + 5
var addExp = Expression.Add(paramExp, intExp);

// x => x + 5
var result = Expression.Lambda<Func<int, int>>(addExp, paramExp).Compile()(3);

Assert.AreEqual(8, result);

在編寫表達式樹時,我總是發現在嘗試使用表達式樹編寫結果表達式之前先以人類可讀的形式編寫結果表達式會更容易。

所以第一步是——你想得到什么? number => number + 0嗎?

如果是這種情況,那就是 lambda 表達式。 你想要做的是開始將結果表達式解構為更小的表達式部分。 在這種情況下,我們有 lambda 表達式的左側是number和 lambda 表達式的右側是number + 0

我們在這里看到了什么? 有一個int類型的參數稱為number ,還有一個int類型的常量值,其值為0 這里還有什么 - Add表達式。

所以你首先定義你的參數:
var numberParamer = Expression.Parameter(typeof(int), "number");

然后你定義你的常數:
var constant = Expression.Constant(0);

然后定義添加表達式:
var addExpression = Expression.Add(constant, numberParamer);

最后,lambda:

var lambda = Expression.Lambda<Func<int, int>>(
  addExpression, // the first argument represents right side of the lambda
  numberParamer // the second argument takes a variable number of values, 
                // depending on the number of your parameters on the left side of your lambda. In this case, one
);

現在你可以這樣稱呼它:
var result = lambda.Compile()(number) ;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM