بخش 1 از Delegates: متدهای افزونه با استفاده از Delegates
این پست فقط برای آشنایی اولیه با Delegates در سی شارپ است، در پست های بعدی به صورت پیشرفته تر در مورد Delegates صحبت خواهم کرد.
Delegate چیست؟
یک Delegate، شیءایی است که می داند چگونه یک متد را فراخوانی کند.
متغیرها در سی شارپ را می شناسید، درست است؟ یک Delegate یک متغیر از نوع ارجاعی (Reference Type) است که ارجاع به یک متد را در خود نگه می دارد و این ارجاع می تواند در زمان اجرا (Runtime) تغییر کند.
از Delegates معمولاً برای پیاده سازی رویدادها (Events) و متدهای بازگشتی (Call-back Methods) استفاده می شود (به زودی به این موضوع برمی گردیم).
قبل از شروع، بیایید نحوه نوشتن (Syntax) یک Delegate را ببینیم:
نحوه نوشتن (Syntax)
delegate int Transformer(int x);
کلیدواژه delegate الزامی است و پس از آن باید نوع خروجی و پارامترها تعریف شوند.
Delegate با نام Transformer با هر متدی که نوع خروجی int و یک پارامتر ورودی از نوع int داشته باشد، سازگار است، مانند:
int Square(int a)
{
return a * a;
}
یا:
int Square(int a) => a * a;
حالا، باید از آن استفاده کنیم، درست است؟
برای استفاده، باید یک متغیر از نوع Transformer بسازید و یک متد به آن نسبت دهید:
Transformer transformer = Square;
در کد بالا، ما یک نمونه (Instance) از Delegate داریم. برای فراخوانی نمونه Delegate، باید دقیقاً مثل یک متد عمل کنید:
int result = transformer(3); // مقدار 9 را برمی گرداند
کد کامل:
Transformer transformer = Square;
int result = transformer(3);
int Square(int a) => a * a;
delegate int Transformer(int x);
به زبان ساده، با استفاده از Delegates، ما یک قاعده یا قرارداد برای متغیرهای خاص تعریف می کنیم که می توانند متدهایی را که از آن قاعده پیروی می کنند، در خود نگه دارند. در مثال ما، یک قاعده به نام Transformer تعریف کردیم که می گوید: «من می توانم هر متدی را که یک int خروجی می دهد و یک int به عنوان ورودی می گیرد، در خود نگه دارم». از این به بعد، می توانید یک نمونه از من بسازید و از طریق نمونه من، به هر متدی که امضای (Signature) مشابهی دارد، اشاره کنید.
من می توانستم متد Square را در هر جایی صدا بزنم، پس اصلاً چرا به Delegate نیاز دارم!؟ با استفاده از یک Delegate، شما فراخوان (Caller) را از متد هدف (Target Method) جدا (Decouple) می کنید.
متدهای افزونه (Plug-in Methods) با استفاده از Delegates
یک متغیر از نوع Delegate در زمان اجرا (Runtime) به یک متد نسبت داده می شود! با استفاده از این ویژگی، می توانید متدهای افزونه (Plug-in Methods) بنویسید. استفاده از Delegates برای متدهای افزونه در سی شارپ، راهی عالی برای ایجاد سیستمی منعطف و قابل توسعه است که در آن می توانید بدون تغییر در کدهای اصلی، قابلیت های مختلف را به صورت پویا اضافه و استفاده کنید. بیایید یک مثال ساده برای نشان دادن این مفهوم ایجاد کنیم:
فرض کنید در حال ساخت یک برنامه ماشین حساب (Calculator) هستیم و می خواهیم به کاربران اجازه دهیم تا عملیات های سفارشی (Custom Operations) را تعریف کنند که بتوانند به ماشین حساب اضافه (Plug-in) شوند. ما از یک Delegate برای تعریف ساختار متد افزونه استفاده می کنیم.
public delegate int CustomOperation(int a, int b);
Delegate سفارشی CustomOperation یک متد را نشان می دهد که دو عدد صحیح می گیرد و یک عدد صحیح برمی گرداند. این ساختار متدهای افزونه ما خواهد بود.
حالا، بیایید کلاس ماشین حساب (Calculator) خود را ایجاد کنیم:
public class Calculator
{
// نمونه Delegate برای نگهداری متد افزونه
private CustomOperation customOperation;
// متد برای تنظیم افزونه عملیات سفارشی
public void SetCustomOperation(CustomOperation operation)
{
customOperation = operation;
}
// متد برای انجام محاسبه با استفاده از عملیات افزونه
public int PerformCustomOperation(int a, int b)
{
if (customOperation != null)
return customOperation(a, b);
else
throw new InvalidOperationException("هیچ عملیات سفارشی تنظیم نشده است.");
}
}
حالا، باید از ماشین حساب با متد افزونه استفاده کنیم:
class Program
{
static void Main(string[] args)
{
Calculator calculator = new Calculator();
// تعریف یک عملیات سفارشی (افزونه)
CustomOperation customOperation = (a, b) => a * a + b * b;
// یا
// CustomOperation customOperation = SomeOperation;
//
// int SomeOperation(int a, int b)
// {
// return a * a + b * b;
// }
// تنظیم عملیات سفارشی در ماشین حساب
calculator.SetCustomOperation(customOperation);
// استفاده از عملیات سفارشی
int result = calculator.PerformCustomOperation(3, 4);
Console.WriteLine("نتیجه عملیات سفارشی: " + result); // خروجی: 25
}
}
کمی گیج کننده است و نیاز به توضیح بیشتری دارد، اینطور نیست؟ به همین دلیل من اینجا هستم! اجازه دهید توضیح دهم:
البته، ما می توانستیم متدهای عملیاتی خود را مانند جمع، تفریق، ضرب، تقسیم و غیره را در کلاس ماشین حساب ایجاد کنیم، اما در آن صورت به متدهای کلاس ماشین حساب وابسته (Coupling) می شدیم، که به این معنی است که هر بار که نیاز به اضافه یا حذف یک عملیات داشته باشیم، باید کلاس ماشین حساب را اصلاح کنیم، درست است؟
در مورد استفاده از ویژگی متد افزونه در مثال ما چطور؟ با استفاده از این ویژگی، ما واقعاً کلاس ماشین حساب و فراخوان (متد Main) را از هم جدا (Decouple) کردیم، ما عملیات را در متد Main تعریف کرده و در زمان اجرا به ماشین حساب اضافه/نسبت می دهیم. با استفاده از این روش، می توانیم متدها را بدون نیاز به اصلاح کلاس ماشین حساب، به آن اضافه یا از آن حذف کنیم.
نظرات (0)
نظر خود را بنویسید
هنوز نظری ثبت نشده است