💡 مفهوم Delegates (دلیگیتها): شیئی که متدها را صدا میزند
Delegate
یک شیء است که میداند چگونه یک متد را فراخوانی کند. 📞
یک نوع دلیگیت (Delegate Type) نوع متدی را که نمونههای آن دلیگیت میتوانند فراخوانی کنند، تعریف میکند. به طور خاص، نوع بازگشتی متد و انواع پارامترهای آن را مشخص میکند. تعریف زیر، یک نوع دلیگیت به نام Transformer را تعریف میکند:
delegate int Transformer (int x);
Transformer
با هر متدی که دارای نوع بازگشتی int و یک پارامتر int باشد، سازگار است، مانند این متد:
int Square (int x) { return x * x; }
// یا به شکل کوتاهتر:
int Square (int x) => x * x;🤝 ایجاد و فراخوانی دلیگیت
تخصیص یک متد به یک متغیر دلیگیت، یک نمونه دلیگیت (Delegate Instance) ایجاد میکند:
Transformer t = Square; // ایجاد نمونه دلیگیت
شما میتوانید یک نمونه دلیگیت را دقیقاً مانند یک متد فراخوانی کنید:
int answer = t(3); // answer برابر 9 میشود
مثال کامل:
Transformer t = Square; // Create delegate instance
int result = t(3); // Invoke delegate
Console.WriteLine (result); // 9
int Square (int x) => x * x;
delegate int Transformer (int x); // Delegate type declaration
یک نمونه دلیگیت، به معنای واقعی کلمه، به عنوان نماینده (Delegate) برای فراخواننده عمل میکند: فراخواننده دلیگیت را فراخوانی میکند، و سپس دلیگیت متد هدف را صدا میزند. 🔄 این عدم وابستگی (Indirection)، فراخواننده را از متد هدف جدا میکند.
نکته فنی: عبارت
Transformer t = Square;
در حقیقت کوتاه شدهی
Transformer t = new Transformer (Square);
است. هنگامی که به Square بدون پرانتز اشاره میکنیم، از یک "Method Group" استفاده میکنیم. اگر متد Overload شده باشد، #C بر اساس امضای دلیگیتی که به آن اختصاص داده میشود، Overload صحیح را انتخاب میکند.
همچنین، عبارت t(3) کوتاه شدهی t.Invoke(3) است. 💡
دلیگیتها شبیه به Callback هستند که یک اصطلاح کلیتر است و ساختارهایی مانند اشارهگرهای تابع C را شامل میشود.
🔌 نوشتن متدهای Plug-in با دلیگیتها
یک متغیر دلیگیت در زمان اجرا، متد را به خود میگیرد. این قابلیت برای نوشتن متدهای Plug-in بسیار مفید است.
در مثال زیر، ما یک متد کاربردی به نام Transform داریم که یک تابع تبدیل (Transform) را روی هر عنصر از یک آرایه اعمال میکند. متد Transform دارای یک پارامتر دلیگیت است که میتوانید از آن برای تعیین تابع Plug-in استفاده کنید:
int[] values = { 1, 2, 3 };
Transform (values, Square); // Hook in the Square method
foreach (int i in values) Console.Write (i + " "); // خروجی: 1 4 9
// پیادهسازی متد Transform
void Transform (int[] values, Transformer t)
{
for (int i = 0; i < values.Length; i++)
values[i] = t (values[i]);
}
int Square (int x) => x * x;
int Cube (int x) => x * x * x;
delegate int Transformer (int x);ما میتوانیم به سادگی با تغییر Square به Cube در خط دوم کد، نوع تبدیل را عوض کنیم. 🔄
متد Transform ما یک تابع مرتبه بالاتر (Higher-Order Function) است، زیرا تابعی است که یک تابع دیگر را به عنوان آرگومان میپذیرد. (یک متد که یک دلیگیت را برمیگرداند نیز یک تابع مرتبه بالاتر محسوب میشود.) 🧠
🤔 جمعبندی و تجربه شما
به نظر شما، مهمترین کاربرد دلیگیتها (به خصوص قبل از معرفی Lambda Expressions و Action/Func) در معماری کدهای #C چه بود؟
🔖 هشتگها:
#CSharp #Delegates #AdvancedCSharp #OOP #Callback