Lambda Expressionها، خیلی شبیه به Anonymous Methodها (Delegateها) هستند.که در پست قبلی در مورد آن توضیح دادم .در واقع عبارتهای Lambda Expression نوعی مختصرتر و روانتر از نوع Anonymous Method است که در سی شارپ 3 به بعد توسط مایکروسافت ارایه شد .
مهمترین و پرکاربردترین موارد استفاده از این عبارت در linq است .
اکنون سعی می کنیم گام به گام از Anonymous Method به سمت Lambda Expression حرکت کنیم .
برای اینکار فرض کنید یک عبارت delegate داریم ، برای رسیدن به Lambda Expression اقدامات زیر را انجام می دهیم :
ابتدا کلمه delegate را حذف می کنیم .
اپراتور <= را در بین اعلان پارامترها و بدنه تابع قرار می دهیم . این اپراتوار را goes to می نامند . شکل زیر دو عبارت را با هم مقایسه می کند .
در شکل بالا دقت کنید تا متوجه شوید چگونه یک عبارت Anonymous Method براحتی تبدیل به یک عبارت Lambda Expression شده است .
عبارت بالا هنوز کاملا خلاصه نشده است . باز هم می توان آن را خلاصه تر کرد.
برای اینکار به سورس کد زیر دقت کنید
Le1 این عبارت درست است اما ما در اینجا از کمترین امکان خلاصه سازی استفاده کرده ایم ما در اینجا فقط کلمه delegate را حذف کردیم و عبارت <= را اضافه کرده ایم
Le2 ما در عبارتهای Lambda Expression می توانیم اعلان صریح نوع متغیر (پارامتر ورودی ) را حذف کنیم و اعلان نکنیم مثال حالت دوم را ببینید و فقط آن را در میان پرانتز محصور می کنیم .
Le3 در اینجا باز هم فراتر می رویم اینجا علاوه بر حذف اعلان نوع پارامتر ورودی پرانتز را هم می توانیم حذف کنیم
Le4 و سرانجام به خلاصه ترین حالت می رسیم که هم اعلان نوع پارامتر ورودی و هم پرانتز و هم آکولادها و هم کلمه کلیدی return قابل حذف شدن هستند
در واقع ما در عبارتهای Lambda Expression ، پارامترهای خودمان را می توانیم بصورت غیر صریح یعنی بدون مشخص کردن نوع آنها ، اعلام کنیم . و اگر متد ما دارای یک خط باشد دیگر نیازی به آکولاد محصور کننده کد نداریم . اما اگر بیش از یک خط باشد باید کد بدنه بین آکولادها باشد
در زیر فرم کلی عبارتهای Lambda Expression را بصورتی کاملا واضح بیان می کنیم .
بر گرفته از کتاب Illustrated C# 2008
لینکهای مفید :
در پست قبلی در مورد delegate صحبت کردیم ، اگر دقت کنید delegate ابتدا می بایست توسط یک متد با نام اعلان می شد و سپس بر اساس همان متدی با امضای یکسان ، لیستی از متدهای دیگر به آن اضافه می شد .
اما در سی شارپ 2 شما می توانید delegate مورد نظر را در بدنه ی کد خود و بدون نیاز به تعریف متد مجزا اعلان کنید . در واقع اینجا ما با متدهایی سرو کار خواهیم داشت که بی نام هستند . در واقع می توان گفت استفاده از متدهای بی نام ، به نوعی کد نویسی را کاهش می دهد. ما در هر جا که لازم داشتیم می توانیم فورا یک متد بی نام استفاده کنیم .
در عکس بالا مشاهده می کنید که در طرف چپ از همان روش معمولی delegate با متدهای نام دار استفاده می کند اما در سمت چپ ما همان کلاس را می بینیم با این تفاوت که در اینجا از متد بی نام استفاده کردیم و دیگر نیازی به اعلانهای متد و delegate نداریم و از همه مهمتر می بینیم که چقدر کد ما خوانا تر و خلاصه تر شده است .
برای درک بهتر مطلب خواندن لینکهای زیر بسیار مفید هستند .
http://www.codeproject.com/KB/cs/InsideAnonymousMethods.aspx
http://msdn.microsoft.com/en-us/library/0yw3tz5k.aspx
Delegates می تواند شی باشد که شامل لیستی از متدهای یکسان (هم امضا و دارای مقادیر بازگشتی یکسان )
تعریف متدهای یکسان و هم امضا : به متدهایی گفته می شود که دارای ساختار یکسان باشند یعنی تعداد و مقادیر و نوع پارامترها ورودی و خروجی یکسان است .
وقتی یک delegates فراخوانی میشود ، تمام متدهای آن نیز فراخوانده می شوند . مانند شکل زیر :
به لیست متدها invocation list می گوییم . پس هر وقت نام این اصطلاح را شنیدیم باید بدانیم که منظور لیست متدهای موجود در delegates است .
این متدها می توانند از هر کلاس یا ساختار باشند . تنها نکته مهم در مورد آنها این است که باید هم امضا و یکسان باشند .ما در واقع یک لیستی ایجاد می کنیم که دارای ساختاری منسجم و سپس تمام متدهایی که دارای همان ساختار هستند را در این لیست قرار می دهیم . تا در نهایت بتوانیم همه این متدها را یکجا فراخوانی کنیم .
فرم کلی تعریف delegate
Delegate نام مقدار بازگشتی delegate (پارامترها)
مثلا :
delegate void MyDel ( int x );
در تعریف مثال بالا ما یک delegate تعریف کردیم که می تواند متدهایی را بپذیرد که هیچ مقدار برگشتی ندارند و در مقابل پارامتر ورودی از نوع عدد صحیح دارند. نام این delegate برابر با mydel است . تعریف بالا صرفا یک اعلان ازنوع delegate است .
شما باید تفاوت بین اعلان از نوع delegate و شی یا object از نوع delegate را بدانید .
وقتی ما delegate را اعلان می کنیم . در حقیقت ما یک لیست را قانون مندی را تعریف می کنیم که اشیا باید با همان قانون و فرم در آن قرار بگیرند . شکل زیر مبین همین تفاوت است .
حال اگر دقت کنید تعریف delegate بسیار شبیه به تعریف یک متد است با این تفاوت که :
تعریف delegate باید حتما با واژه اصلی و کلیدی delegate همراه باشد
در تعریف delegate ، متد های ما دارای بدنه نیستند . و فقط اعلان می شوند.
تعریف شی delegate
بعد از آنکه ما شیی از نوع delegate تعریف کردیم برای استفاده از delegate در برنامه باید شیی از نوع delegate تعریف کنیم . اما قبل از تعریف شی ما باید حداقل یک متد با ساختار متد delegate داشته باشیم . تا بتوانیم آن را در لیست delegate قرار دهیم .
مثلا برای delegate مثال بالا ، باید متدی داشته باشیم با همان فرم
private void myMethod (int i)
{
// method body
}
اکنون می توانیم با استفاده از تعریف زیر متد ما را به لیست delegate اضافه کنیم .
Mydel Delvar = new mydel(mymethod);
همانطور که می بینید ما یک متد با همان ساختار delegate به لیست invocation list اضافه کردیم .
اما همانطور که در ابتدا گفتم ، ما به لیست invocation list می توانیم چندین متد اضافه کنیم یا حذف کنیم .
اضافه کردن متدها به invocation list بسیار ساده است فرض کنید متدی دیگر با همان فرم delegate داریم .
private void myMethod۲ (int i)
{
// method body
}
برای اضافه کردن متد جدید از دستور زیر استفاده می کنیم :
Delvar +=new mydel(mymethod2);
ترتیب متدها در delegate را در شکل زیر مشاهده کنید :
و سرانجام برای حذف متدی از لیست delegate بصورت زیر عمل می کنیم .
Delvar - =new mydel(mymethod2);
با دستور زیر متد از لیست خارج می شود .
حال اگر آبجکت delegate مورد نظر را فراخوانی کنیم، تمام متدهایی که در Invocation List آن موجود هستند اجرا میشوند، نحوه فراخوانی کردن یک آبجکت delegate مانند فراخوانی یک متد و ارسال پارامتر (در صورت نیاز) به آن میباشد :
مثال زیر را :
Delvar(55);
با استفاده از دستور بالا عدد 55 به عنوان پارامتر به تمام متدها ارسال می شود وتمام متدهای موجود در Invocation List به ترتیب قرار گرفتن در لیست Invocation List اجرا می شوند .
یک مثال کاربری کنسول را دانلود کنید تا کمی در دنیای واقعی بهتر متوجه مطلب شوید . همچنین برای فهم دقیقتر مطلب می توانید از کتاب
Illustrated C# 2008 از انتشارات Apress استفاده کنید