عبارت های لامبدا (Lambda Expressions)
سی شارپ 2.0 متدهای بینام را معرفی کرد، که تا اینجا این گونه از متدها را بررسی کردیم. هرچند املاء متدهای بینام تا حدودی طولانی بوده و نیاز به اطلاعاتی دارد که خود کامپایلر از آنها مطلع است. بجای اینکه مجبور باشید این اطلاعات تکراری را الحاق کنید، سی شارپ 3.0 عبارت های لامبدا را معرفی کرده که املاء و نگارش متدهای بینام را کاهش داده است. شاید بخواهید بجای استفاده از متدهای بینام از عبارت های لامبدا استفاده کنید. در حقیقت، اگر عبارت های لامبدا زودتر معرفی شده بودند، دیگر هرگز متدهای بینام وجود نداشتند.
در نگارش متدهای بینام، کلمه کلیدی delegate مازاد بر احتیاج است؛ به این علت که خود کامپایلر می بیند که شما درحال انتساب متد به delegate هستید. شما می توانید با انجام کارهای زیر، بسادگی، یک متد بینام را به یک عبارت لامبدا تبدیل کنید:
- کلیدواژه delegate را حذف کنید.
- عملگر لامبدا ( <= ) را مابین لیست پارامترها و بدنه متد بی نام قرار دهید. عملگر لامبدا بصورت "می رود به" (goes to) خوانده میشود.
تکه کد زیر این تبدیل را نشان می دهد. خط اول یک متد بی نام را که به متغیر del انتساب داده شده را نشان می دهد. خط دوم همان متد بی نام را بعد از آنکه به عبارت لامبدا تبدیل شده را نشان می دهد که به متغیر le1 منتسب شده است.
MyDel del = delegate(int x) { return x + 1; } ; // Anonymous method
MyDel le1 = (int x) => { return x + 1; } ; // Lambda expression
خوبه بدونید که:
اصطلاح "عبارت لامبدا" از جبر و حساب لامبدا (Lambda calculus) می آید، که در دهه 1920 و 1930 توسط ریاضی دان هایی مثل آلونزو چرچ (Alonzo Church) و دیگران توسعه داده شد. Lambda calculus سیستمی برای نمایش توابع است و از حرف یونانی لامبدا (λ) برای نمایش یک تابع بینام استفاده می کند. اخیرا" زبان های برنامه نویسی تابع گرا از جمله Lisp از این اصطلاح برای نشان دادن عبارت هایی که مستقیما" اعلان یک تابع را بیان می کنند، استفاده می کند، بجای اینکه یک نام برای آن بکار ببرد.
این تبدیل ساده، کوتاه تر بوده و واضح تر به نظر میرسد، ولی فقط باعث صرفه جویی در 6 کاراکتر می شود. البته چیزی های بیشتری هستند که کامپایلر می تواند آنها را حدس زده و عبارت های لامبدا را ساده تر کند، که در زیر به آنها اشاره شده است.
- کامپایلر همچنین از اعلان delegate ، نوع پارامترهای آن را می داند. پس عبارت های لامبدا به شما اجازه می دهند که نوع پارامترها را (همانطور که در انتساب le2 می بینید) تغییر دهید.
- به پارامتر هایی که به همراه نوعشان در لیست نوشته می شوند، explicitly typed (نوع صریح) گفته میشود.
- به پارامتر هایی که بدون نوعشان در لیست پارامترها نوشته می شوند، implicitly typed (نوع ضمنی) گفته میشود.
- اگر فقط یک پارامتر نوع ضمنی وجود داشته باشد، شما می توانید از پرانتزها صرف نظر کنید؛ بصورتی که در انتساب le3 دیده میشود.
- در نهایت، عبارت های لامبدا اجازه می دهند که بدنه شان یک عبارت باشد یا یک بلوک از بیان های مختلف. اگر بلوک بیان ها فقط حاوی یک بیان برگشتی (بیانی که در آن کلیدواژه return وجود دارد) باشد، شما می توانید بلوک بیان را با عبارتی که بعد از کمه کلیدی return میآید جایگزین کنید؛ بصورتی که در انتساب le4 دیده می شود.
MyDel del = delegate(int x) { return x + 1; } ; // Anonymous method
MyDel le1 = (int x) => { return x + 1; } ; // Lambda expression
MyDel le2 = (x) => { return x + 1; } ; // Lambda expression
MyDel le3 = x => { return x + 1; } ; // Lambda expression
MyDel le4 = x => x + 1 ; // Lambda expression
قالب نهایی عبارت لامبدا تقریبا" دارای یک-چهارم کاراکترهای متد بینام است؛ واضح تر بوده و برای فهمیدن و درک آن راحتر است. کد زیر تمام انواع تبدیلات را نشان می دهد. اولین خط تابع Main یک متد بینام را نشان میدهد که به متغیر del انتساب داده شده است. خط دوم همان متد بینام را بعد از تبدیل شدن به عبارت لامبدا نشان میدهد، که به متغیر le1 انتساب داده شده است.
delegate double MyDel(int par);
class Program
{
static void Main()
{
MyDel del = delegate(int x) { return x + 1; }; // Anonymous method
MyDel le1 = (int x) => { return x + 1; }; // Lambda expression
MyDel le2 = (x) => { return x + 1; };
MyDel le3 = x => { return x + 1; };
MyDel le4 = x => x + 1;
Console.WriteLine("{0}", del(12));
Console.WriteLine("{0}", le1(12)); Console.WriteLine("{0}", le2(12));
Console.WriteLine("{0}", le3(12)); Console.WriteLine("{0}", le4(12));
}
}
این کد نتیجه زیر را تولید میکند:
13
13
13
13
13
چند نکته مهم در مورد لیست پارامتر عبارت های لامبدا در زیر آمده است:
- پارامترهای موجود در لیست پارامترهای عبارت های لامبدا باید با همتای خود در delegate ، از نظر تعداد، نوع، و مکان قرار گیری همخوانی داشته باشند.
- پاارمتر های موجود در لیست پارامترهای عبارت، مجبور نیستند که نوع پارامتر را مطرح کنند(نوع ضمنی)، بجز در مواردی که پارامترها ref یا out باشند که در این موارد باید نوع آنها صراحتا" اعلان شود (نوع صریح).
- اگر فقط یک پارامتر موجود است و آن هم بصورت ضمنی نوعش مشخص است، می توان از پرانتزهای اطراف لیست پارامترها صرف نظر کرد. در غیر این صورت باید از پرانتزها استفاده کرد.
- اگر هیچ پارامتری وجود ندارد، شما می توانید از پرانتزهای خالی استفاده کنید.
شکل زیر املاء و نگارش عبارت های لامبدا را نشان می دهد.
نحوه نوشتن عبارت های لامبدا به این صورت است که درسمت چپ قسمت پارامترها و در سمت راست بدنه عبارت نوشته می شود و بین پارامترها و بدنه از عملگر لامبدا ( <= ) استفاده میکنیم.