آموزش Lambda Expressions در زبان سی شارپ
Lambda Expressions یک راه کوتاه تر برای نمایش متدهای anonymous با قواعد نحوی (syntax) خاص است که در نسخه سوم زبان برنامه نویسی سی شارپ (.NET 3.5) معرفی شد.
به منظور ایجاد Lambda Expressions، باید پارامترهای ورودی را (در صورت وجود) در سمت راست عملگر => مشخص کنید (به عملگر =>، عملگر لامبدا گفته می شود) و دستور یا بلوک دستورات را در سمت راست بنویسید. تصویر زیر شکل کلی یک عبارت لامبدا را نشان می دهد:
برای مثال در عبارت لامبدا x => x * x یک پارامتر به نام x مشخص شده است و مقدار خروجی که این عبارت باز می گرداند مربع آن x خواهد بود. شما می توانید این عبارت را مانند نمونه زیر با استفاده از delegate نیز پیاده سازی کنید.
delegate int del(int i); static void Main(string[] args) { del myDelegate = x => x * x; int j = myDelegate(5); //j = 25 }
پیاده سازی مثال بالا با Expression Trees
using System.Linq.Expressions; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Expression<del> myET = x => x * x; } } }
عبارات لامبدا (Lambda Expressions)
به مجموعه پارامتر ها و دستوراتی که در دو طرف عملگر => قرار می گیرند، عبارت لامبدا گفته می شود. عبارات لامبدا به طور گسترده در ساخت Expression Tree ها مورد استفاده قرار می گیرند.
syntax یک عبارت لامبدا را در زیر مشاهده می کنید:
(input-parameters) => expression
گذاشتن پارانتز در صورتی فقط یک پارامتر وجود داشته باشد، اختیاری است. اما در صورتی که تعداد آن ها بیش از یک عدد باشد، باید از پارانتز استفاده شود. پارامترها با کاما (,) از یکدیگر جدا می شوند.
مانند نمونه زیر:
(x, y) => x == y
گاهی اوقات ممکن است کامپایلر در تشخیص نوع پارامترها دچار مشکل شود. در این زمان می توانید نوع پارامترها را به طور صریح مانند نمونه زیر مشخص کنید:
(int x, string s) => s.Length > x
زمانی که عبارت لامبدا هیچ پارامتری نداشته باشد، می توانید از پارانتز خالی استفاده کنید.
مانند نمونه زیر:
() => SomeMethod()
بدنه یک عبارت لامبدا می تواند شامل فراخوانی یک متد باشد، مانند نمونه بالا. شما می توانید در بدنه عبارت لامبدا با استفاده از {} هر تعداد خط کد که لازم داشته باشید را بنویسید.
شکل کلی آن به صورت زیر است:
(input-parameters) => { statement; }
مثال
delegate void TestDelegate(string s);
یا
TestDelegate del = n => { string s = n + " World"; Console.WriteLine(s); };
Async در عبارات لامبدا
شما به راحتی می توانید در عبارات لامبدا از متدهای ناهمگام (Asynchronous Methods) و کلمات کلیدی async و await استفاده کنید. برای نمونه، مثال زیر را در نظر بگیرید که در آن یک هندلر برای رویداد کلیک یک دکمه نوشته شده است و در داخل این هندلر یک متد async فراخوانی شده است.
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private async void button1_Click(object sender, EventArgs e) { // ExampleMethodAsync returns a Task. await ExampleMethodAsync(); textBox1.Text += "\r\nControl returned to Click event handler.\n"; } async Task ExampleMethodAsync() { // The following line simulates a task-returning asynchronous process. await Task.Delay(1000); } }
معادل کد فوق با استفاده از عبارت لامبدا به صورت زیر خواهد بود (کلمه کلیدی async باید قبل از لیست پارامترها نوشته شود):
public partial class Form1 : Form { public Form1() { InitializeComponent(); button1.Click += async (sender, e) => { // ExampleMethodAsync returns a Task. await ExampleMethodAsync(); textBox1.Text += "\nControl returned to Click event handler.\n"; }; } async Task ExampleMethodAsync() { // The following line simulates a task-returning asynchronous process. await Task.Delay(1000); } }
استفاده از لامبدا در LINQ
بیشتر متدهای LINQ دارای پارامترهایی از نوع generic delegates هستند (مانند Where و Count). بنابراین شما می توانید از عبارات لامبدا به عنوان پارامتر این متدها استفاده کنید. در مثال زیر یک مجموعه از اعداد صحیح تعریف شده است سپس با استفاده از متد Count و عبارت لامبدا تعداد اعداد فرد موجود در این مجموعه را مشخص می شود (اعدادی که باقی ماننده تقسیم آن ها بر ۲ مساوی ۱ باشد، فرد هستند).
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; int oddNumbers = numbers.Count(n => n % 2 == 1);
حوزه متغیرها در عبارات لامبدا
قوانین مربوط به حوزه متغیرها مشابه بلوک های تو در تو است. به طوری که در بدنه یک عبارت لامبدا می توان به متغیرهای بیرونی که در حوزه متد قرار دارند دسترسی داشت. برای آن که بتوانید از یک متغیر بیرونی در داخل حوزه لامبدا استفاده کنید، باید ابتدا آن را مقدار دهی کنید.
به مثال زیر توجه کنید:
delegate bool D(); delegate bool D2(int i); class Test { D del; D2 del2; public void TestMethod(int input) { int j = 0; // Initialize the delegates with lambda expressions. // Note access to 2 outer variables. // del will be invoked within this method. del = () => { j = 10; return j > input; }; // del2 will be invoked after TestMethod goes out of scope. del2 = (x) => {return x == j; }; // Demonstrate value of j: // Output: j = 0 // The delegate has not been invoked yet. Console.WriteLine("j = {0}", j); // Invoke the delegate. bool boolResult = del(); // Output: j = 10 b = True Console.WriteLine("j = {0}. b = {1}", j, boolResult); } static void Main() { Test test = new Test(); test.TestMethod(5); // Prove that del2 still has a copy of // local variable j from TestMethod. bool result = test.del2(10); // Output: True Console.WriteLine(result); Console.ReadKey(); } }
نکات
- از لحاظ تقدم عملگرها، عملگر => با عملگر = برابر است.
- در سمت چپ عبارات لامبدا نمی توان از عملگر های is یا as استفاده کرد.
- تمام محدودیت هایی که در متدهای anonymous وجود دارند، در عبارات لامبدا نیز اعمال می شوند.
- متغیر تعریف شده در داخل بدنه عبارت لامبدا، در بیرون از آن قابل دسترسی نیست.
- دستور return در داخل بدنه عبارت لامبدا به معنای پایان اجرای متد نیست.
- در داخل بدنه عبارت لامبدا نمی توان از دستور break و دستور continue و goto استفاده کرد.
- عبارات لامبدا در متدهای مبتنی بر کوئری های LINQ به عنوان آرگومان استفاده می شوند (مانند متد Where).
لینک های مفید
- Anonymous Methods
- Delegates
- Expression Trees
نوشته آموزش (عبارات لامبدا) Lambda Expressions در زبان سی شارپ اولین بار در سورس سرا - آموزش برنامه نویسی. پدیدار شد.