Compartilhar via


Expressões lambda (guia de programação translation from VPE for Csharp)

A expressão lambda é uma função anônima que pode conter expressões e instruções e pode ser usada para criar delegados ou tipos de árvore de expressão.

Todas sistema autônomo expressões lambda usam o operador lambda =>, que é lido sistema autônomo "vai para".O lado esquerdo do operador lambda Especifica os parâmetros de entrada (se houver) e à direita contém o bloco de expressão ou demonstrativo.O de expressão lambda x => x * xé lido "x vai para o x horas x." Esta expressão pode ser sistema autônomo assinado para um tipo delegado sistema autônomo segue:

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

Para criar um tipo de árvore de expressão:

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

The => operador tem a mesma precedência de atribuição)=) e é associativos à direita.

Lambdas são usados no método com base LINQ consultas sistema autônomo argumentos para métodos de operadores de consulta padrão sistema autônomo Where e Where.

Quando você usa a sintaxe de método para telefonar o Where método na Enumerable classe (sistema autônomo você faz no LINQ para objetos e LINQ to XML) o parâmetro é um tipo delegado System.Func<T, TResult>. Uma expressão lambda é a maneira mais conveniente para criar esse delegado.Quando você chama o método mesmo no, por exemplo, System.Linq.Queryable classe (sistema autônomo você faz no LINQ to SQL), o tipo de parâmetro é um System.Linq.Expressions.Expression<func>onde Func é qualquer delegados Func com até cinco parâmetros de entrada. Novamente, uma expressão lambda é apenas uma maneira bem concisa para construir a árvore de expressão.Os lambdas permitem que o Where chamadas para aparência semelhante, embora na verdade o tipo de objeto criado a partir do lambda é diferente.

No exemplo anterior, observe que a assinatura do delegado possui um tipo implícito parâmetro de entrada de digitar inte retorna um int. A expressão lambda pode ser convertida em um delegado do tipo porque ele também tem um parâmetro de entrada (x) e um valor retornado que o compilador pode converter implicitamente digitar int. (inferência de tipos de tipos é discutida mais detalhadamente as seções a seguir). Quando o delegado é chamado usando um parâmetro de entrada de 5, ele retorna um resultado de 25.

Lambdas não são permitidos no lado esquerdo do é or sistema autônomo operador.

Todas as restrições que se aplicam a métodos anônimo também se aplicam a expressões lambda.Para obter mais informações, consulte Métodos anônimos (Guia de programação do C#).

Expressão lambdas

Uma expressão lambda com uma expressão no lado direito é chamada um expressão lambda.Expressão lambdas são bastante usados na construção de Árvores de Expressão. Uma expressão lambda retorna o resultado da expressão e assume a forma básica a seguir:

(input parameters) => expression

Os parênteses são opcionais apenas se o lambda tem um parâmetro de entrada; caso contrário, eles são necessários.Dois ou mais parâmetros de entrada são separados por vírgulas entre parênteses:

(x, y) => x == y

Às vezes é difícil ou impossível para o compilador a inferir os tipos de entrada.Quando isso ocorrer, você pode especificar sistema autônomo tipos explicitamente mostrado no exemplo a seguir:

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

Especifica zero parâmetros de entrada com parênteses vazios:

() => SomeMethod()

Observe no exemplo anterior que o corpo de uma expressão lambda pode consistir em uma telefonar de método.No entanto, se você estiver criando árvores de expressão serão consumidos em outro domínio, sistema autônomo o SQL servidor, você não deve usar chamadas de método em expressões lambda.Os métodos terão não representam nada fora do contexto do .NET common linguagem tempo de execução.

demonstrativo lambdas

Uma demonstrativo de lambda é semelhante a uma expressão lambda, exceto pelo fato de que o comando (s) está entre chaves:

(input parameters) => {statement;}

O corpo do lambda demonstrativo pode consistir em qualquer número de instruções; no entanto, na prática há normalmente não mais que duas ou três.

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

demonstrativo lambdas, assim como os métodos anônimo, não podem ser usados para criar árvores de expressão.

Lambdas com operadores de consulta padrão

Muitos operadores de consulta padrão têm um parâmetro de entrada cujo tipo é um do Func<T, TResult> família de representantes genéricos. The Func<T, TResult> delegados usar parâmetros de tipo para definir o número e tipo de parâmetros de entrada e o tipo de retorno do delegado. Func delegados são muito úteis para encapsular expressões definidas pelo usuário que são aplicadas a cada elemento em um conjunto de dados de fonte. Por exemplo, considere o seguinte tipo de delegado:

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

O delegado pode ser instanciado sistema autônomo Func<int,bool> myFunc onde int é um parâmetro de entrada e bool é o valor retornado. O valor retornado sempre é especificado no parâmetro de tipo último.Func<int, string, bool> define um delegado com dois parâmetros de entrada, int e stringe um tipo de retorno de bool. A seguir Func delegado, quando ele é chamado, retornará true ou false para indicar se o parâmetro de entrada é igual a 5:

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

Você também pode fornecer uma expressão lambda quando o tipo de argumento é um Expression<Func>, por exemplo, em operadores de consulta padrão definidos no sistema.Linq.Queryable. Quando você especifica um Expression<Func> argumento, a lambda será ser compilado em uma árvore de expressão.

Um operador de consulta padrão, a Count método, é mostrado aqui:

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

O compilador pode inferir o tipo de parâmetro de entrada ou você pode também especificá-lo explicitamente.Essa expressão lambda determinada conta esses inteiros (n) que quando divididos por dois têm um resto de 1.

O método a seguir produzirá uma sequência que contém todos os elementos da matriz de números que ocorrem antes de 9 “ ” porque esse é o primeiro número na sequência que não atenda a condição:

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

Este exemplo mostra como especificar vários parâmetros de entrada, colocando-os entre parênteses.O método retorna todos os elementos da matriz de números até que seja um número encontrou cujo valor é menor que a sua posição.Não confunda o operador lambda (=>) com o operador igual ou superior (>=).

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

inferência de tipos de tipos em lambdas

Quando lambdas escrita, você geralmente não têm que especificar um tipo nos parâmetros de entrada porque o compilador pode inferir o tipo com base no corpo do lambda, base delegado tipo e outros fatores sistema autônomo descrito no translation from VPE for Csharp 3.0 linguagem Specification.Para a maioria dos operadores de consulta padrão, a primeira entrada é o tipo dos elementos na sequência de fonte.Portanto, se você estiver consultando uma IEnumerable<Customer>, e, em seguida, a variável de entrada é inferida para ser um Customer objeto, significando que você tem acesso a seus métodos e propriedades:

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

sistema autônomo regras Geral para lambdas são:

  • O lambda deve conter o mesmo número de parâmetros sistema autônomo o tipo de delegado.

  • Cada parâmetro de entrada a lambda deve ser implicitamente conversível em seu parâmetro delegado correspondente.

  • O valor retornado de lambda (se houver) deve ser implicitamente conversível no tipo de retorno do delegado.

Observe que as expressões lambda em si mesmos não tem um tipo porque o common type sistema tem há intrínseco conceito de "expressão lambda." No entanto, às vezes é conveniente fala informalmente de "tipo" de uma expressão lambda.Nesses casos o tipo refere-se ao tipo delegado ou Expression tipo ao qual a expressão lambda é convertida.

Escopo de variável de expressões lambda

Lambdas pode se referir a variáveis externas que estão no escopo no método ou tipo no qual a lambda é definido delimitador.Variáveis que são capturadas dessa maneira são armazenadas para uso na expressão lambda, mesmo se variáveis caso contrário, deve ir fora do escopo e ser coletados pelo lixo.Uma variável externa definitivamente deve ser atribuída antes que ele pode ser consumido em uma expressão lambda.O exemplo a seguir demonstra estas regras:

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();
        }
    }

As seguintes regras se aplicam ao escopo de variável em expressões lambda:

  • Uma variável que é capturada não serão lixo-coletada até que o delegado que faz referência a ele sai do escopo.

  • As variáveis introduzidas em uma expressão lambda não são visíveis no método externo.

  • Uma expressão lambda não pode capturar diretamente um ref ou out parâmetro de um método de encerramento.

  • Uma demonstrativo return em uma expressão lambda não faz com que o método delimitador para retornar.

  • Uma expressão lambda não pode conter um goto demonstrativo, break demonstrativo, ou continue demonstrativo cujo destino fora do corpo ou no corpo de um contidos anônimo função.

Especificação da linguagem C#

Para obter mais informações, consulte a seção a seguir no Especificação da linguagem C#:

  • 5.3.3.29 Funções anônimas

Consulte também

Conceitos

Guia de Programação C#

Árvores de Expressão

Referência

Métodos anônimos (Guia de programação do C#)

é (translation from VPE for Csharp Reference)

Outros recursos

Language-Integrated Query (LINQ)

As expressões lambda recursiva