C#'s lamda expression use

Introduction  

Lambda expression is an anonymous function that can be used to create delegates or expression tree types, but it is more concise than anonymous functions.

By using lambda expressions, you can write local functions that can be passed as parameters or returned as function call values. Lambda expressions are particularly useful for writing LINQ query expressions.

Lambda expression itself can be divided into two types: statement Lambda and expression Lambda.

To create a Lambda expression, you need  to specify the input parameters (if any) on the left side of the Lambda operator  => (goes to), and then enter the expression or statement block on the other side.

format

(input parameters) => expression

or 

(input parameters) => {statement;}

The parameter list on the left can have multiple parameters, one parameter, or no parameters; the parameter type can be implicit or explicit, and the parameter type can be ignored because it can be inferred according to the context of use.

The parentheses are optional only when the lambda has only one input parameter; otherwise, the parentheses are required.

For example:
                (x, y) => x * y //Multiple parameters, implicit type => expression
                x => x * 10 //Single parameter, implicit type => expression
                x => {return x * 10 ;} //Single parameter, implicit type => statement block
                (int x) => x * 10 //Single parameter, explicit type => expression
                (int x) => {return x * 10;} // Single parameter, explicit type => statement block
                () => Console.WriteLine() //no parameter

For example, a lambda expression  x => x * x specifies a named  x parameter and returns  x the squared value. 

Lambda expressions and delegate types

As shown in the following example, you can assign this expression to the delegate type:

 

delegate int del(int i); 
static void Main(string[] args) 
{ 
    del myDelegate = x => x * x; 
    int j = myDelegate(5); //j = 25 
}

 

=> The operator has the =same precedence as the assignment operator ( ) and is a right associative operation

It is most convenient to create this delegate using a Lambda expression.

 Lambda expressions can be converted to delegate types, but the following points must be met: 
        1. The two parameters have the same number of 
        parameters. 2. The parameter types are the same. Note that implicit types must participate in type discrimination 
        . 3. The return type of the delegate must be the same as that of Lambda. , Whether it is an expression or a statement block

Comparison of Lambda and anonymous functions:

 

 

public delegate int DelegateTest(int n1, int n2);
        static void Main(string[] args)
        {
            //委托:方法作为参数传递
            var r1 = Result(3, 4, Sum);  
            //使用匿名方法传递委托
            var r4 = Result(3,4,delegate(int x,int y){return x+y;});
            //语句lambda传递委托
            var r2 = Result(3, 4, (a, b) => { return a - b; }); 
            //lambda传递委托
            var r3 = Result(3, 4, (a, b) => a * b); 
            Console.ReadLine();
        }
        public static int Result(int a, int b, DelegateTest @delegate)
        {
            return @delegate(a, b);
        }
        public static int Sum(int a, int b)
        {
            return a + b;
        }

 

Func and Lambda

Simplifies the amount of code even more. At this time, you don’t need to declare that the delegate can be used directly as above.

 

public static void LambdaFunc()
        {
            Func<string, string, string> getFunc = (p1, p2) =>
            {
                return p1 + "    " + p2;
            };
          Console.WriteLine(getFunc("我是第一个参数","我是第二个参数"));
        }

 

Linq和Lambda

   //Get all user IDs

            List<string> gidList = Users.Select(p => p.Gid).ToList();

           //Get all collections greater than 6

            aaList = retList.Where(p => p > 6).ToList();

Asynchronous lambda

By using the async and await keywords, you can easily create lambda expressions and statements that include asynchronous processing. For example, the following Windows Form example contains an ExampleMethodAsyncevent handler that calls and waits for asynchronous methods  .

 

 

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        button1.Click += async (sender, e) =>
        {
            await ExampleMethodAsync();
            textBox1.Text += "\r\nControl returned to Click event handler.\n";
        };
    }

    private async Task ExampleMethodAsync()
    {
        // The following line simulates a task-returning asynchronous process.
        await Task.Delay(1000);
    }
}

 

The internal mechanism of lambda expressions

Lambda expressions are not inherent constructions within the CLR. Their implementation is generated by the C# compiler at compile time. Lambda expressions provide a corresponding C# and language construct for the "declaration of delegates in-line" mode. Therefore, when we write a lambda, the compiler will actually generate a series of codes. Take the above code as an example, and use the decompiler tool to view the generated equivalent code:

In the Main method, a lambda expression is used to pass the delegate, and the anonymous function is generated after compilation. This also proves that the lambda mentioned above is actually a simplified anonymous function.

Let's take a look at the above anonymous method delegate (int x, int y) (return x + y;) and lambad expression (a, b) => {return a-b; }, (a, b) => a * b) After compilation, 3 static methods <Main>b_0, <Main>b_1 and <Main>b_2 are actually generated, that is to say, these 3 static methods are respectively instantiated into delegates when they are called and used as The parameter passing is back to the original understanding of the delegate: the delegate implementation passes the method as a parameter to another method.

Expression tree

An expression tree is a code that allows lambda expressions to be expressed as a tree-like data structure instead of executable logic.

Creation of expression tree:

1. Create an expression tree through Lambda expressions

 The following code demonstrates that lambda expressions are represented as executable code and expression trees:

   Func<int, int> res = x => x + 1;               //Code 
   Expression<Func<int, int>> exp = x => x + 1;   //Data

After the above assignment, the delegate res refers to the method that returns x+1, and the expression tree exp refers to the data structure describing the expression x=>x+1. This is the obvious difference between the two.

2. Create an expression tree through the API

    To use the API to create an expression tree, you need to use the Expression class. This class provides static methods to create a specific type of expression tree node, for example: ParameterExpression (representing a variable or parameter) or MethodCallExpression (representing a method call). The following demonstrates using the API to create an expression tree:

 

 

static void Main(string[] args)
        {//创建表达式树:Expression<Func<int, int>> exp = x => x + 1;
            ParameterExpression param = Expression.Parameter(typeof(int),"x");
            ConstantExpression value = Expression.Constant(1, typeof(int));
            BinaryExpression body = Expression.Add(param, value);
            Expression<Func<int, int>> lambdatree = Expression.Lambda<Func<int, int>>(body, param);
            Console.WriteLine("参数param:{0}", param);
            Console.WriteLine("描述body:{0}", body);
            Console.WriteLine("表达式树:{0}", lambdatree);

            //解析表达式树:
            //取得表达式树的参数
            ParameterExpression dparam = lambdatree.Parameters[0] as ParameterExpression;
            //取得表达式树描述
            BinaryExpression dbody = lambdatree.Body as BinaryExpression;
            //取得节点
            ParameterExpression left = dbody.Left as ParameterExpression;
            ConstantExpression right = body.Right as ConstantExpression;
            Console.WriteLine("解析出的表达式:{0}=>{1} {2} {3}", param.Name, left.Name, body.NodeType, right.Value);
            Console.ReadLine();
        }

 

operation result:

Regarding the expression tree: the introduction of the concept of expression tree allows the program to compile a lambda expression into data to represent it, instead of compiling it into a specific implementation (static method) represented as a delegate. Using this feature, libraries such as Linq to Sql and Linq to Xml can interpret expression trees and use them in contexts other than CIL.

Guess you like

Origin blog.csdn.net/liyang_nash/article/details/104647418