الـ Lambda Expression هو وظيفة Function بدون اسم تحتسب وتعيد قيمة وحيدة كما يمكن استخدامها في التعابير التي تطلب إجراءات مفوضة Delegate والمثال التالي عن هذه التعابير يأخذ قيمة ويعيد الناتج بعد إضافة واحد لها
Function (num As Integer) num + 1
كما يمكنك إسناد هذه الوظيفة لمتغير وتمرير القيمة له
Dim add1 = Function(num As Integer) num + 1 Console.WriteLine(add1(5))
كما يمكنك تعريف وتنفيذ الوظيفة بنفس الوقت
Console.WriteLine((Function(num As Integer) num + 1)(5))
كما يمكن أن تستخدم Lambda Expressions كقيمة معادة عند استدعاء وظيفة أو تمريرها كوسيط لإجراء مفوض ففي المثال التالي تستخدم Lambda Expressions بوليانية كوسائط للإجراء testResult حيث تطبق الطريقة فحص بولياني لوسيط من النوع Integer ويظهر القيمة Success إذا كانت قيمة Lambda Expression هي True أو Failure إن كانت قيمته 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وتكون صيغتها على الشكل
• هذه التعابير لا تملك اسما
• لا يمكن استخدام المعدلات معها مثل Overloads أو Overrides
• لا تستخدم قسم AS لتحديد نوع القيمة المعادة وبدلا عن ذلك يكون نوع القيمة المعادة هو نوع القيمة التي يشكلها جسم الإجراء فإن كان جسم الإجراء مثلا Cust.City = "London" فتكون القيمة المعادة بوليانية
• جسم الإجراء يجب أن يكون تعبير وليس تصريح ويمكن أن يحتوي على استدعاء لوظيفة Function ولكنه لا يمكن أن يستدعي إجراء Sub
• لا يوجد تعبير Return وتكون القيمة المعادة هي قيمة ذلك التعبير الذي يشكل جسم الوظيفة
• لا يوجد تعبير End
• يجب أن تكون جميع الوسائط محددة النوع أو تكون جميعها بأنواع بالإشارة
• غير مسموح بالوسائط الاختيارية
• الوسائط Generic غير مسموح بها
ونتيجة لهذه القواعد سنرى أن أي تعبير Lambda Expression سيكون بسيطا وغير معقد
تشترك Lambda Expression مع الوظائف Methods بأنها محددة ولها جميع حقوق الوصول كأي كود مكتوب في الطريقة التي تحتويها وهذا يتضمن الوصول إلى متغيرات الأعضاء والوظائف وجميع المغيرات الموجودة في الوظيفة التي تحتوي التعبير Lambda Expression ففي المثال التالي المتغير target هو محلي بالنسبة لـ makeTheGame والطريقة التي تم تحديد التعبير Lambda Expression فيها هي playTheGame لاحظ أن القيمة المعادة من التعبير Lambda Expression يتم تعيينها لـ takeAGuess في Main مازالت تستطيع الوصول للمتغير المحلي 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ويستعرض المثال التالي مجالا عريضا من حقوق الوصول المعششة في Lambda Expression فعندما يتم تنفيذ التعبير Lambda Expression من Main كـ aDel يستخدم العناصر التالية ( حقل في الفئة aField – خاصية في الفئة aProp – وسيط للإجرائية functionWithNestedLambda هو level1 – متغير محلي لـ functionWithNestedLambda هو localVar – وسيط للتعبير Lambda Expression المعشش هو 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كما يمكن تحويل Lambda Expressions لتتوافق مع الإجراءات المفوضة فعندما تعين Lambda Expression لإجراء مفوض Delegate يمكنك تحديد أسماء الوسائط ولكن مع إغفال أنواع البيانات الخاصة بها تاركا مهمة تحديدها للإجراء المفوض ففي المثال التالي يتم تعيين Lambda Expression لمتغير اسمه del من النوع ExampleDel الذي هو عبارة عن إجراء مفوض يأخذ وسيطتين integer و string لاحظ أن أنواع المتغيرات في Lambda Expression لم يتم تحديدها ومع ذلك فـ del يتطلب وسيطا من النوع integer ووسيطا آخر من النوع string كما تم تحديده عند تعريف 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.
'Console.WriteLine(del(7, 3))
'Console.WriteLine(del("abc"))في المثال التالي يتم تحديد Lambda Expression ليعيد القيمة True إذا كان الوسيط يمتلك قسمة أو False إذا كان القيمة 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))والمثال التالي يحدد Lambda Expression يعيد Index العنصر الأخير في مصفوفة
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