Lambda expressions and anonymous methods (C # programming guide)

Source: Internet
Author: User

A Lambda expression is an anonymous function that can contain expressions and statements and can be used to create a delegate or expression directory tree.

All lambda expressions use the lambda Operator The operator reads "goes ". The left side of the lambda operator is the input parameter (if any), and the right side contains the expression or statement block. Lambda expressions x => X * X are read as "X goes to X times X ". You can assign this expression to the delegate type as follows:

delegate int del(int i);del myDelegate = x => x * x;int j = myDelegate(5); //j = 25

Create expression directory tree type:

using System.Linq.Expressions;// ...Expression<del> = x => x * x;

=> The operator has the same priority as the value assignment operator (=) and is a right combination operator.

Lambda is used in method-based LINQ queries, such And where (iqueryable, String, array <Object> [] () []) and other standard query operator parameters.

Use the method-based syntax in Class The parameter is the delegate type when the method is used (like in LINQ to objects and LINQ to XML ). . Using lambda expressions to create a delegate is the most convenient. For example, when you When the same method is called in the class (as in LINQ to SQL), the parameter type is <Func>, in which func is any func delegate that contains up to five input parameters. Similarly, lambda expressions are just a very concise way to construct the expression directory tree. Although the types of objects created through Lambda are actually different, Lambda makesWhereThe call looks similar.

In the previous example, note that the delegate signature has an implicit type input parameter of the int type and returns the int type. A Lambda expression can be converted to a delegate of this type because it also has an input parameter (X) and a compiler can implicitly convert the return value to an int type. (Type inference will be discussed in detail in the following sections .) When you call a delegate using input parameter 5, it returns Result 25.

In Or Lambda is not allowed on the left side of the operator.

All limitations applicable to anonymous methods also apply to lambda expressions. For more information, see the anonymous method (C # programming guide ).

Lambda expressions

The Lambda expression on the right is called a "Lambda expression ". Lambda expressions are being constructed Is widely used. Lambda expressions return the results of expressions in the following basic form:

(input parameters) => expression

Parentheses are optional only when Lambda has an input parameter; otherwise, parentheses are required. Two or more input parameters are separated by commas (,) enclosed in parentheses:

(x, y) => x == y

Sometimes, the compiler is difficult or unable to deduce the input type. In this case, you can explicitly specify the type as shown in the following example:

(int x, string s) => s.Length > x

Use parentheses to specify zero input parameters:

() => SomeMethod()

In the previous example, note that the body of a Lambda expression can contain method calls. However, if you want to create an expression directory tree that will be used in another domain (such as SQL Server), you should not use method calls in lambda expressions. The method is meaningless outside the context of the. NET public Language Runtime Library.

Lambda statements

Lambda statements are similar to lambda expressions, but they are enclosed in braces:

(input parameters) => {statement;}

The body of a Lambda statement can contain any number of statements. However, there are usually no more than two or three statements.

delegate void TestDelegate(string s);…TestDelegate myDel = n => { string s = n + " " + "World"; Console.WriteLine(s); };myDel("Hello");

Like an anonymous method, Lambda statements cannot be used to create expression directory trees.

Lambda with standard query Operators

Many standard query operators have input parameters, whose types are generic delegated. One of the series. The delegate uses the type parameter to define the quantity and type of input parameters and the return type of the delegate.FuncDelegation is useful for encapsulating User-Defined expressions that are applied to each element in a set of source data. For example, assume that the following types of delegation exist:

public delegate TResult Func<TArg0, TResult>(TArg0 arg0)

You can instantiate the delegate as func <int, bool> myfunc, where Int Is the input parameter and bool is the return value. The return value is always specified in the last type parameter.Func <int, String, bool>Define a delegate that contains two input parameters (INT and string) and returns the bool type. InFuncDuring delegation, the delegate returns true or false to indicate whether the input parameter is equal to 5:

    Func<int, bool> myFunc = x => x == 5;    bool result = myFunc(4); // returns false of course

When the parameter type isExpression <func>You can also provide lambda expressions, such as the standard query operators defined in system. LINQ. queryable. If you specifyExpression <func>Parameter, Lambda will compile as the expression directory tree.

A standard query operator is displayed here, Method:

    int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };    int oddNumbers = numbers.Count(n => n % 2 == 1);

The compiler can infer the type of the input parameter, or you can explicitly specify this type. This special Lambda expression calculates the number of Integers (n). The remainder of these integers is 1 divided by 2.

The following method generates a sequence containing all elements that appear before "9" in the number array, because "9" is the first number in the sequence that does not meet the conditions:

    var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6);

This example shows how to specify multiple input parameters by including the input parameters in parentheses. This method returns all elements in the number array until a number with a value smaller than its position is encountered. Do not confuse Lambda operators (=>) with operators greater than or equal to (> =.

    var firstSmallNumbers = numbers.TakeWhile((n, index) => n >= index);

Type inference in Lambda

When writing lambda, you usually do not need to specify a type for the input parameter, because the compiler can infer the type based on the lambda subject, basic delegate type, and other factors described in the C #3.0 language specification. For most standard query operators, the first input is the type of elements in the source sequence. Therefore, if you want to queryIenumerable <customer>, The input variable is inferred as the customer object, which means you can access its method and attributes:

customers.Where(c => c.City == "London");

The general rules of Lambda are as follows:

  • Lambda must contain the same number of parameters as the delegate type.

  • Each input parameter in Lambda must be implicitly converted to its corresponding delegate parameter.

  • The return value (if any) of Lambda must be implicitly converted to the return type of the delegate.

Note that the lambda expression itself does not have a type, because the general type system does not have the internal concept of "Lambda expression. However, sometimes the lambda expression type is not formally discussed ". In these cases, the type refers to the conversion of the delegate type or Lambda expression Type.

Variable range in lambda expressions

Lambda can reference "external variables" that are within the range of a closed method or type in which Lambda is defined. Variables captured in this way will be stored for use in lambda expressions, even if the variables are otherwise out of range or recycled as garbage. An external variable must be explicitly allocated before it can be used in a Lambda expression. The following example demonstrates these rules:

delegate bool D();    delegate bool D2(int i);    class Test    {        D del;        D2 del2;        public void TestMethod(int input)        {            int j = 0;            // Initialize the delegates with lambda expressions.            // Note access to 2 outer variables.            // del will be invoked within this method.            del = () => { j = 10;  return j > input; };            // del2 will be invoked after TestMethod goes out of scope.            del2 = (x) => {return x == j; };                        // Demonstrate value of j:            // Output: j = 0             // The delegate has not been invoked yet.            Console.WriteLine("j = {0}", j);            // Invoke the delegate.            bool boolResult = del();            // Output: j = 10 b = True            Console.WriteLine("j = {0}. b = {1}", j, boolResult);        }        static void Main()        {            Test test = new Test();            test.TestMethod(5);            // Prove that del2 still has a copy of            // local variable j from TestMethod.            bool result = test.del2(10);            // Output: True            Console.WriteLine(result);                        Console.ReadKey();        }    }

The following rules apply to variable ranges in lambda expressions:

  • The captured variables will not be recycled as garbage until the delegation of the referenced variables exceeds the permitted range.

  • Variables introduced in lambda expressions cannot be seen in external methods.

  • Lambda expressions cannot directly capture the ref or out parameters from the closed method.

  • The Return Statement in the lambda expression does not cause the return of the closed method.

  • Lambda expressions cannot contain goto statements, break statements, or continue statements whose target is located outside or inside the body of the anonymous function.

C # Language Specification

For more information, see the following sections in the C # Language Specification:

  • 5.3.3.29 anonymous Functions

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.