مقدمه
تا به اینجا، هر زمان که میخواستیم یک نماینده (delegate) را به یک متد متصل کنیم، ابتدا یک متد
کامل و با نام مشخص تعریف میکردیم و سپس نام آن را به نماینده اختصاص میدادیم. این روش کاملاً
کارآمد است، اما زمانی که منطق متد بسیار کوتاه و ساده است و فقط در یک نقطه از برنامه استفاده
میشود، تعریف یک متد جداگانه میتواند باعث پراکندگی و شلوغی بیمورد کد شود. برای حل این مشکل،
C# 2.0 ویژگیای به نام متدهای ناشناس (Anonymous Methods) را معرفی
کرد. یک متد ناشناس به ما اجازه میدهد تا یک بلوک کد را به صورت "درونخطی" (inline) و بدون نام،
مستقیماً به یک نماینده اختصاص دهیم.
متد ناشناس چیست؟
یک متد ناشناس، همانطور که از نامش پیداست، متدی است که نامی ندارد. این یک بلوک کد است که مستقیماً
در جایی که یک نمونه از نماینده انتظار میرود، نوشته میشود. این ویژگی به خصوص برای ثبتنام در
رویدادها (events) با منطقهای کوتاه بسیار مفید است، زیرا کد مربوط به کنترل رویداد را دقیقاً در
کنار کد ثبتنام آن نگه میدارد و خوانایی را افزایش میدهد.
سینتکس متدهای ناشناس
برای تعریف یک متد ناشناس، از کلمهی کلیدی delegate استفاده میکنیم که به دنبال آن یک لیست
پارامتر (اختیاری) در داخل پرانتز و سپس بلوک کد در داخل آکولاد {} میآید.
delegate (parameter-list) { };
بیایید یک مثال ساده را ببینیم. فرض کنید یک نماینده از نوع Action<string> داریم که میخواهیم آن
را به یک منطق ساده برای چاپ یک پیام متصل کنیم.
Program.cs
Action<string> printMessage = delegate (string message)
{
Console.WriteLine(message);
};
printMessage("Hello from an anonymous method!");
در این کد، ما به جای تعریف یک متد جداگانه، منطق چاپ پیام را مستقیماً به متغیر
printMessage
اختصاص دادهایم. این بلوک کد نامی ندارد و فقط از طریق نمایندهای که به آن اشاره میکند، قابل
فراخوانی است.
یک نکتهی جالب در مورد متدهای ناشناس این است که اگر متد شما پارامتری نگیرد، میتوانید لیست
پارامتر را به طور کامل حذف کنید.
Program.cs
Action printTime = delegate
{
Console.WriteLine($"Current time: {DateTime.Now.ToShortTimeString()}");
};
printTime();
یک مثال کاربردیتر: کنترل رویداد
همانطور که اشاره شد، یکی از کاربردهای اصلی متدهای ناشناس، کنترل رویدادهاست. فرض کنید یک کلاس
Button داریم که یک رویداد Click را فراهم میکند.
Program.cs
public class Button
{
public event EventHandler Click;
public void SimulateClick()
{
Click?.Invoke(this, EventArgs.Empty);
}
}
Button myButton = new();
myButton.Click += delegate (object sender, EventArgs e)
{
Console.WriteLine("Button was clicked!");
Console.WriteLine($"Sender was: {sender.GetType().Name}");
};
myButton.SimulateClick();
در این مثال، به جای تعریف یک متد جداگانه مانند MyButton_Click، ما منطق کنترل رویداد را
مستقیماً در زمان ثبتنام (+=) تعریف کردهایم. این کار باعث میشود
کدی که به هم مرتبط هستند، در
کنار هم قرار بگیرند و درک آن سادهتر شود.
سیر تکاملی به سمت عبارات لامبدا
متدهای ناشناس یک قدم بزرگ در سادهسازی کد در C# 2.0 بودند. با این حال، سینتکس آنها
هنوز کمی طولانی و دارای کلمات کلیدی اضافی (delegate) بود. در C# 3.0، یک سینتکس
بسیار مختصرتر و قدرتمندتر به نام عبارات لامبدا (Lambda Expressions) معرفی شد که
تقریباً به طور کامل جایگزین متدهای ناشناس شد.
بیایید تکامل یک نماینده را ببینیم:
- متد با نام (C# 1.0):
void MyHandler(object s, EventArgs e) { ... }
button.Click += MyHandler;
- متد ناشناس (C# 2.0):
button.Click += delegate(object s, EventArgs e) { ... };
- عبارت لامبدا (C# 3.0 و بعد):
button.Click += (s, e) => { ... };
همانطور که میبینید، عبارات لامبدا بسیار کوتاهتر هستند. در برنامهنویسی مدرن C#، شما
تقریباً همیشه از عبارات لامبدا استفاده خواهید کرد. با این حال، درک متدهای ناشناس برای خواندن
کدهای قدیمیتر و فهمیدن اینکه عبارات لامبدا در پشت صحنه چه کاری انجام میدهند، بسیار مفید است.
در درس بعدی به طور کامل به بررسی عبارات لامبدا خواهیم پرداخت.