Share via


Expressions lambda

Mise à jour : novembre 2007

Une expression lambda est une fonction sans nom qui calcule et retourne une valeur unique. Les expressions lambda peuvent être utilisées chaque fois qu'un type délégué est valide.

Remarque :

L'instruction RemoveHandler est une exception. Vous ne pouvez pas passer d'expression lambda pour le paramètre de délégué de RemoveHandler.

L'exemple suivant est une expression lambda qui incrémente son argument et retourne la valeur.

Function (num As Integer) num + 1

Parce qu'une expression lambda est une expression, elle ne peut être utilisée que dans le cadre d'une instruction.

Par exemple, vous pouvez affecter la fonction à un nom de variable, en particulier si vous voulez l'utiliser à plusieurs reprises.

Dim add1 = Function(num As Integer) num + 1

Pour appeler la fonction, envoyez une valeur pour le paramètre.

' The following line prints 6.
Console.WriteLine(add1(5))

Vous pouvez également déclarer et exécuter simultanément la fonction.

Console.WriteLine((Function(num As Integer) num + 1)(5))

Une expression lambda peut être retournée comme valeur d'un appel de fonction (comme le montre l'exemple de la section Contexte ultérieurement dans cette rubrique) ou passée comme argument à un paramètre de délégué. Dans l'exemple suivant, les expressions lambda booléennes sont passées comme argument au testResult de méthode. La méthode applique le test booléen à un argument entier, value, et affiche « Opération réussie » si l'expression lambda retourne la valeur True lorsqu'elle est appliquée à value, ou « Échec de l'opération » si elle retourne la valeur False.

Module Module2

    Sub Main()
        ' The following line will print Success, because 4 is even.
        testResult(4, Function(num) num Mod 2 = 0)
        ' The following line will print Failure, because 5 is not > 10.
        testResult(5, Function(num) num > 10)
    End Sub

    ' Sub testResult takes two arguments, an integer value and a 
    ' Boolean function. 
    ' If the function returns True for the integer argument, Success
    ' is displayed.
    ' If the function returns False for the integer argument, Failure
    ' is displayed.
    Sub testResult(ByVal value As Integer, ByVal fun As Func(Of Integer, Boolean))
        If fun(value) Then
            Console.WriteLine("Success")
        Else
            Console.WriteLine("Failure")
        End If
    End Sub

End Module

Expressions lambda dans les requêtes

Dans LINQ (Language Integrated Query), les expressions lambda sont à la base de beaucoup des opérateurs de requête standard. Le compilateur crée des expressions lambda pour capturer les calculs définis dans des méthodes de requête fondamentales, telles que Where, Select, Order By, Take While et d'autres.

Prenons par exemple la requête suivante :

Dim londonCusts = From cust In db.Customers 
                  Where cust.City = "London" 
                  Select cust

Cet exemple est compilé dans le code suivant :

Dim londonCusts = db.Customers _
    .Where(Function(cust) cust.City = "London") _
    .Select(Function(cust) cust)

Pour plus d'informations sur les méthodes de requête, consultez Requêtes (Visual Basic).

Syntaxe d'expression lambda

La syntaxe d'une expression lambda ressemble à celle d'une fonction standard. Les différences sont les suivantes :

  • Une expression lambda n'a pas de nom.

  • Les expressions lambda ne peuvent pas avoir modificateurs, tels que Overloads ou Overrides.

  • Les expressions lambda n'utilisent pas de clause As pour désigner le type de retour de la fonction. À la place, le type est déduit de la valeur que le corps de l'expression lambda prend. Par exemple, si le corps de l'expression lambda est Where cust.City = "London", son type de retour est Boolean.

  • Le corps de la fonction doit être une expression, pas une instruction. Le corps peut se composer d'un appel à une procédure de fonction, mais pas d'un appel à une sous-procédure.

  • Il n'existe aucune instruction Return. La valeur retournée par la fonction est celle de l'expression du corps de la fonction.

  • Il n'existe aucune instruction End Function.

  • Tous les paramètres doivent posséder des types de données spécifiés ou être tous déduits.

  • Les paramètres facultatifs et Paramarray ne sont pas autorisés.

  • Les paramètres génériques ne sont pas autorisés.

En raison de ces restrictions et des façons dont les expressions lambda sont utilisées, ils sont habituellement courts et peu complexes.

Contexte

Une expression lambda partage son contexte avec la méthode dans laquelle elle est définie. Elle possède les mêmes droits d'accès que tout code écrit dans la méthode contenante. Cela inclut l'accès aux variables membre, fonctions, sous-routines, Me, paramètres et variables locales dans la méthode contenante.

L'accès aux variables et aux paramètres locaux dans la méthode contenante peut s'étendre au delà de la durée de vie de cette méthode. Tant qu'un délégué qui fait référence à une expression lambda n'est pas disponible pour l'opération garbage collection, l'accès aux variables dans l'environnement d'origine est conservé. Dans l'exemple suivant, la variable target est locale à makeTheGame, la méthode dans laquelle l'expression lambda playTheGame est définie. Notez que l'expression lambda retournée, assignée à takeAGuess dans Main, a encore accès à la variable locale target.

Module Module1

    Sub Main()
        ' Variable takeAGuess is a Boolean function. It stores the target
        ' number that is set in makeTheGame.
        Dim takeAGuess As gameDelegate = makeTheGame()

        ' Set up the loop to play the game.
        Dim guess As Integer
        Dim gameOver = False
        While Not gameOver
            guess = CInt(InputBox("Enter a number between 1 and 10 (0 to quit)", "Guessing Game", "0"))
            ' A guess of 0 means you want to give up.
            If guess = 0 Then
                gameOver = True
            Else
                ' Tests your guess and announces whether you are correct. Method takeAGuess
                ' is called multiple times with different guesses. The target value is not 
                ' accessible from Main and is not passed in.
                gameOver = takeAGuess(guess)
                Console.WriteLine("Guess of " & guess & " is " & gameOver)
            End If
        End While

    End Sub

    Delegate Function gameDelegate(ByVal aGuess As Integer) As Boolean

    Public Function makeTheGame() As gameDelegate

        ' Generate the target number, between 1 and 10. Notice that 
        ' target is a local variable. After you return from makeTheGame,
        ' it is not directly accessible.
        Randomize()
        Dim target As Integer = CInt(Int(10 * Rnd() + 1))

        ' Print the answer if you want to be sure the game is not cheating
        ' by changing the target at each guess.
        Console.WriteLine("(Peeking at the answer) The target is " & target)

        ' The game is returned as a lambda expression. The lambda expression
        ' carries with it the environment in which it was created. This 
        ' environment includes the target number. Note that only the current
        ' guess is a parameter to the returned lambda expression, not the target. 

        ' Does the guess equal the target?
        Dim playTheGame = Function(guess As Integer) guess = target

        Return playTheGame

    End Function

End Module

L'exemple suivant montre la large gamme de droits d'accès de l'expression lambda imbriquée. Lorsque l'expression lambda retournée est exécutée depuis Main sous la forme aDel, elle accède aux éléments suivants :

  • Un champ de la classe dans laquelle elle est définie : aField

  • Une propriété de la classe dans laquelle elle est définie : aProp

  • Un paramètre de la méthode functionWithNestedLambda, dans laquelle elle est définie : level1

  • Une variable locale de functionWithNestedLambda : localVar

  • Un paramètre de l'expression lambda dans laquelle elle est imbriquée : level2

Module Module3

    Sub Main()
        ' Create an instance of the class, with 1 as the value of 
        ' the property.
        Dim lambdaScopeDemoInstance = New LambdaScopeDemoClass _
            With {.Prop = 1}

        ' Variable aDel will be bound to the nested lambda expression  
        ' returned by the call to functionWithNestedLambda.
        ' The value 2 is sent in for parameter level1.
        Dim aDel As aDelegate = _
            lambdaScopeDemoInstance.functionWithNestedLambda(2)

        ' Now the returned lambda expression is called, with 4 as the 
        ' value of parameter level3.
        Console.WriteLine("First value returned by aDel:   " & aDel(4))

        ' Change a few values to verify that the lambda expression has 
        ' access to the variables, not just their original values.
        lambdaScopeDemoInstance.aField = 20
        lambdaScopeDemoInstance.Prop = 30
        Console.WriteLine("Second value returned by aDel: " & aDel(40))
    End Sub

    Delegate Function aDelegate(ByVal delParameter As Integer) _
        As Integer

    Public Class LambdaScopeDemoClass
        Public aField As Integer = 6
        Dim aProp As Integer

        Property Prop() As Integer
            Get
                Return aProp
            End Get
            Set(ByVal value As Integer)
                aProp = value
            End Set
        End Property

        Public Function functionWithNestedLambda _
           (ByVal level1 As Integer) As aDelegate
            Dim localVar As Integer = 5

            ' When the nested lambda expression is executed the first 
            ' time, as aDel from Main, the variables have these values:
            ' level1 = 2
            ' level2 = 3, after aLambda is called in the Return statement
            ' level3 = 4, after aDel is called in Main
            ' locarVar = 5
            ' aField = 6
            ' aProp = 1
            ' The second time it is executed, two values have changed:
            ' aField = 20
            ' aProp = 30
            ' level3 = 40
            Dim aLambda = Function(level2 As Integer) _
                              Function(level3 As Integer) _
                                  level1 + level2 + level3 + localVar _
                                  + aField + aProp

            ' The function returns the nested lambda, with 3 as the 
            ' value of parameter level2.
            Return aLambda(3)
        End Function

    End Class
End Module

Conversion en type délégué

Une expression lambda peut être convertie implicitement en type délégué compatible. Pour plus d'informations sur les exigences générales de compatibilité, consultez Conversion simplifiée des délégués.

De plus, lorsque vous assignez des expressions lambda aux délégués, vous pouvez spécifier les noms de paramètres, mais omettre leurs types de données, en permettant l'extraction des types du délégué. Dans l'exemple suivant, une expression lambda est assignée à une variable nommée del de type ExampleDel, un délégué qui accepte deux paramètres, un entier et une chaîne. Remarquez que les types de données des paramètres dans l'expression lambda ne sont pas spécifiés. Toutefois, del requiert un argument entier et un argument de chaîne, comme spécifié dans la définition de ExampleDel.

' Definition of function delegate ExampleDel.
Delegate Function ExampleDel(ByVal arg1 As Integer, _
                             ByVal arg2 As String) As Integer
' Declaration of del as an instance of ExampleDel, with no data 
' type specified for the parameters, m and s.
Dim del As ExampleDel = Function(m, s) m

' Valid call to del, sending in an integer and a string.
Console.WriteLine(del(7, "up"))

' Neither of these calls is valid. Function del requires an integer
' argument and a string argument.
' Not valid.
' Console.WriteLine(del(7, 3))
' Console.WriteLine(del("abc"))

Exemples

  • L'exemple suivant définit une expression lambda qui retourne la valeur True si l'argument nullable a une valeur assignée, et False si sa valeur est Nothing.

    Dim notNothing = Function(num? As Integer) _
                 num IsNot Nothing
    Dim arg As Integer = 14
    Console.WriteLine("Does the argument have an assigned value?")
    Console.WriteLine(notNothing(arg))
    
  • L'exemple suivant définit une expression lambda qui retourne l'index du dernier élément dans un tableau.

    Dim numbers() As Integer = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
    Dim lastIndex = Function(intArray() As Integer) _
                        intArray.Length - 1
    For i = 0 To lastIndex(numbers)
        numbers(i) = numbers(i) + 1
    Next
    

Voir aussi

Tâches

Comment : passer des procédures à une autre procédure en Visual Basic

Comment : créer une expression lambda

Concepts

Procédures dans Visual Basic

Introduction à LINQ dans Visual Basic

Délégués et opérateur AddressOf

Types valeur nullables

Conversion simplifiée des délégués

Référence

Function, instruction (Visual Basic)