عبارات لامبدا (Lambda expressions)

عبارات لامبدا (Lambda expressions) ساده شده دستور زبان متدهای بی نام هستند. به عنوان مثال در برنامه زیر از یک متد بی نام که به یک delegate ارجاع داده شده است استفاده شده است.

using System;

public delegate void MessageDelegate(string message);

public class Program
{
    public static void Main()
    {
        MessageDelegate ShowMessage = new MessageDelegate( 
        delegate(string message)                           
        {                                                  
         Console.WriteLine(message);                       
        }                                                  
        );                                                 

        ShowMessage("Hello World!");
    }
}

به وسیله عبارات لامبدا می‌توان کد بالا را به صورت ساده‌تری نوشت :

using System;

public delegate void MessageDelegate(string message);

public class Program
{
    public static void Main()
    {
        MessageDelegate ShowMessage = (message) => Console.WriteLine(message);

        ShowMessage("Hello World!");
    }
}

مقایسه متد بی نام و عبارت لامبدا :

MyDelegate del = delegate(int x)    { return x + 1; } ;     // متد بی نام
MyLambda   lam =         (    x) => { return x + 1; } ;     // عبارت لامبدا

در عبارت لامبدا ابتدا پارامترها را بدون ذکر نوعشان می‌نویسیم و بعد از عملگر => استفاده می‌کنیم. سپس دستوراتی را که قرار است اجرا شوند را می‌نویسیم. نوع پارامترها به صورت خودکار به وسیله کامپایلر تشخیص داده می‌شود. البته امضاء عبارات لامبدا باید شبیه به امضاء delegate باشد. عبارات لامبدا دارای اشکال زیادی هستند. به عنوان مثال در مثال بالا از یک عبارت لامبدایی استفاده کرده‌ایم که دارای یک دستور ساده اجرایی است. اگر delegate شما برای عبارت لامبدا هیچ پارامتری نداشته باشد، همه کاری که لازم است نجام دهید این است که هیچ پارامتری در داخل عبارت لامبدا قرار ندهید.

MessageDelegate ShowMessage = () => Console.WriteLine("Hello");

به این نکته توجه کنید که شما می‌توانید نوع پارامترهای عبارت لامبدا را نشان دهید.

MessageDelegate ShowMessage = (string message) => Console.WriteLine(message);

اگر نوع یک پارامتر را مشخص کنید، باید نوع سایر پارامترها را نیز مشخص کنید. به عنوان مثال نمی‌توانید به صورت زیر عمل کنید :

MessageDelegate ShowMessage = (string message1, message2) =>
       Console.WriteLine(message1);

اگر عبارات لامبدای شما دارای چندین دستور اجرایی باشند می‌توانید آنها را داخل آکولاد قرار دهید. به عبارت لامبدایی که دارای آکولاد باشد دستور لامبدا می گویند.

MessageDelegate ShowMessage = (message) =>
{
        Console.WriteLine(message);
        Console.WriteLine("Some more message");
}

در زیر مثالی از یک عبارت لامبدا که دارای مقدار برگشتی است نشان داده شده است :

SampleDelegate GetSquare = (number) => { return number * number; };

به این نکته توجه کنید که هنگام استفاده از دستور return باید همیشه از دستورات لامبدایی استفاده کنید که دارای آکولاد می‌باشند. اگر یک عبارت لامبدا فقط دارای یک دستور return ساده باشد می‌توانید به سادگی آن را به expression lambda تبدیل کنید.

SampleDelegate GetSquare = (number) => (number * number);

به این نکته توجه کنید که استفاده از پرانتز در کد بالا برای فهم بهتر آن است. اگر یک عبارت لامبدا دارای یک پارامتر ساده و یک دستور return است، می‌توانید برای سادگی بیشتر پرانتزها را حذف نمایید:

SampleDelegate GetSquare = number => number * number;

ولی اگر یک عبارت لامبدا دارای 2 یا تعداد بیشتری پارامتر باشد باید انها را داخل پرانتز قرار دهید.

SampleDelegate GetSum = (num1, num2) => num1 + num2;

عبارت لامبدای بالا دارای دو پارامتر است و حاصل جمع آنها را بر می‌گرداند.

یک مثال از عبارت لامبدا

با استفاده از عبارات لامبدا راحت‌تر می‌توان متدهای بی نام را به عنوان آرگومان به دیگر متدها ارسال کرد. به مثال زیر توجه کنید :

  1: using System;                                                                       
  2:                                                                                     
  3: namespace LambdaDemo
  4: {                                                                                   
  5:     public delegate int Arithmetic(int x, int y);                                   
  6:                                                                                     
  7:     public class Program                                                            
  8:     {                                                                               
  9:         public static int GetResult(Arithmetic Operation, int num1, int num2)       
 10:         {                                                                           
 11:             return Operation(num1, num2);                                           
 12:         }                                                                           
 13:                                                                                     
 14:         public static void Main()
 15:         {                                                                           
 16:             Console.Write("Enter first number : ");                                  
 17:             int num1 = Convert.ToInt32(Console.ReadLine());                         
 18:             Console.Write("Enter second number: ");                                 
 19:             int num2 = Convert.ToInt32(Console.ReadLine());                         
 20:                                                                                     
 21:             Console.WriteLine("Sum        = " + GetResult((x, y) => x + y, num1, num2));
 22:             Console.WriteLine("Difference = " + GetResult((x, y) => x - y, num1, num2));
 23:             Console.WriteLine("Product    = " + GetResult((x, y) => x * y, num1, num2));
 24:             Console.WriteLine("Quotient   = " + GetResult((x, y) => x / y, num1, num2));
 25:         }                                                                           
 26:     }                                                                               
 27: }
Enter first number : 5
Enter second number: 2
Sum        = 7
Difference = 3
Product    = 10
Quotient   = 2

ابتدا در خط 5 یک delegate ایجاد می‌کنیم که دو آرگومان از نوع اعداد صحیح را قبول کرده و یک مقدار صحیح را بر می‌گرداند. سپس از این delegate به عنوان یکی از پارامترهای متد GetResult() استفاده می‌کنیم (خطوط 12-9). دو پارامتر دیگر، دو عدد هستند که همانطور که خواهیم دید در عملیاتهای مختلف نقش دارند. از آنجاییکه اولین پارامتر یک delegate است، آرگومانی که به آن ارسال می‌شود باید مرجع یک متد، یا یک متد بی نام و یا یک عبارت لامبدا باشد. با استفاده از عبارت لامبدا می‌توان کدهای خواناتری نوشت و همچنین کدنویسی را کاهش داد. در خطوط 24-21 متد GetResult را فراخوانی می‌کنیم. توجه کنید که متد در هر فراخوانی یک عبارت لامبدا را به عنوان اولین آرگومان قبول می‌کند. اگر از متدهای بی نام استفاده می‌کردیم، نیاز به کدنویسی بیشتری داشتیم و خوانایی آن نیز کمتر می‌شد.