Delegate نوعی مرجع به یک متد است. به عبارت سادهتر، میتوانید آن را به عنوان "اشارهگر به متد" در نظر بگیرید که اجازه میدهد آدرس یک متد را ذخیره کرده و آن را بهصورت غیرمستقیم فراخوانی کنید. این شباهتی به اشارهگرهای تابع در زبان C دارد، با این تفاوت که Delegateها نوع ایمن هستند و از بررسیهای نوع در زمان کامپایل بهره میبرند.
Delegate در واقع نوعی "قرارداد" است که مشخص میکند یک متد باید چه نوع ورودیها و خروجیای داشته باشد. این ویژگی باعث میشود تا وابستگی بین کلاسها کاهش یابد و انعطافپذیری در برنامهنویسی افزایش پیدا کند، زیرا میتوان بدون تغییر مستقیم در ساختار کلاسها، متدهای مختلف را به Delegate متصل کرد و به راحتی رفتارهای متنوعی را پیادهسازی نمود. این ویژگی باعث میشود بتوان متدهایی با امضای مشابه را به یک Delegate متصل کرد و با استفاده از آن، به شکل انعطافپذیری از متدهای مختلف استفاده نمود.
تعریف Delegate در سیشارپ
برای تعریف یک Delegate از کلمه کلیدی delegate
استفاده میشود. به عنوان مثال، یک Delegate که به متدهایی با دو ورودی عدد صحیح و یک خروجی عدد صحیح اشاره میکند، به صورت زیر تعریف میشود:
public delegate int MathOperation(int a, int b);
در اینجا، MathOperation
یک Delegate است که میتواند به هر متدی که دو عدد صحیح را به عنوان ورودی دریافت و یک عدد صحیح را به عنوان خروجی برمیگرداند، اشاره کند.
مثالی از استفاده از Delegate
فرض کنید چند متد مختلف دارید که امضای مشابهی دارند و میخواهید بسته به شرایط، یکی از آنها را فراخوانی کنید. میتوانید از Delegate برای این کار استفاده کنید:
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
public int Subtract(int a, int b)
{
return a - b;
}
}
public class Program
{
public static void Main()
{
Calculator calculator = new Calculator();
MathOperation operation;
// اشاره به متد Add
operation = calculator.Add;
Console.WriteLine($"نتیجه جمع: {operation(5, 3)}");
// تغییر به متد Subtract
operation = calculator.Subtract;
Console.WriteLine($"نتیجه تفریق: {operation(5, 3)}");
}
}
در این مثال، Delegate MathOperation
میتواند به دو متد Add
و Subtract
اشاره کند و بسته به نیاز، هر کدام از آنها را فراخوانی کند.
Delegates چندگانه (Multicast Delegates)
یکی از ویژگیهای جالب Delegateها در سیشارپ قابلیت Multicast است. یعنی یک Delegate میتواند به بیش از یک متد اشاره کند و همه آنها را به ترتیب فراخوانی نماید. این امکان زمانی کاربرد دارد که بخواهید چندین عملیات را به صورت زنجیرهای اجرا کنید.
public class Program
{
public static void Main()
{
MathOperation operation = (a, b) => a + b;
operation += (a, b) => a - b;
Console.WriteLine(operation(5, 3)); // در این حالت، تنها نتیجه آخرین متد به عنوان خروجی در نظر گرفته میشود
}
}
در مثال بالا، Delegate operation
ابتدا به متدی برای جمع و سپس به متدی برای تفریق اشاره میکند. با استفاده از عملگر +=
هر دو متد به Delegate اضافه میشوند، اما فقط خروجی آخرین متد به عنوان نتیجه نهایی استفاده میشود. این ویژگی به عنوان Multicast Delegate شناخته میشود و در مواقعی که نیاز به اجرای چندین عملیات به ترتیب دارید، بسیار مفید است.
کاربردهای Delegate در برنامههای واقعی
یکی از مهمترین کاربردهای Delegate در برنامههای واقعی، امکان انجام عملیات غیرمستقیم است. به عنوان مثال، فرض کنید برنامهای با دکمههای مختلف دارید که با کلیک هر کدام، یک عملیات متفاوت انجام میشود. در این حالت، میتوانید به جای مشخص کردن مستقیم متدها، از Delegateها استفاده کنید تا رفتار دکمهها بهصورت پویا قابل تغییر باشد.
این ویژگی بهخصوص در سناریوهایی که نیاز به انعطافپذیری در تعیین رفتار دارید، بسیار مفید است. برای مثال، در فریمورکهای GUI و یا در سناریوهای طراحی الگوهای رفتاری (مثل Strategy Pattern)، Delegate نقش کلیدی ایفا میکند.
الگوهای طراحی (Design Patterns)
از Delegateها میتوان در پیادهسازی الگوهای طراحی مانند Observer و Command استفاده کرد. برای مثال، در الگوی Observer، یک Delegate میتواند برای ثبت و اطلاعرسانی به چندین مشاهدهگر (Observer) استفاده شود. زمانی که وضعیت موضوع تغییر میکند، Delegate به همه مشاهدهگران متصل اطلاع میدهد تا بهروزرسانیهای لازم را انجام دهند. در الگوی Observer، Delegateها به راحتی برای ثبت و اطلاعرسانی به چندین مشاهدهگر (Observer) استفاده میشوند. این کار به شما امکان پیادهسازی رفتارهای پویا و قابل تغییر را میدهد و به افزایش انعطافپذیری برنامه کمک میکند.
معرفی Func و Action
برای تسهیل کار با Delegateها، سیشارپ دو Delegate عمومی به نامهای Func و Action ارائه داده است. Func برای متدهایی استفاده میشود که دارای خروجی هستند، در حالی که Action برای متدهایی که فقط ورودی دارند و خروجی void
دارند به کار میرود. زمانی که به یک متد با خروجی نیاز دارید، از Func استفاده کنید و برای متدهایی که فقط عملیات را بدون خروجی انجام میدهند، از Action بهره ببرید. این Delegateها به شما این امکان را میدهند که بدون نیاز به تعریف Delegateهای سفارشی، متدهایی با ورودیها و خروجیهای مختلف را مدیریت کنید.
Action در سیشارپ
Action یک نوع Delegate است که میتواند تا 16 پارامتر به عنوان ورودی داشته باشد، اما هیچ خروجیای ندارد. در واقع، Action برای متدهایی استفاده میشود که فقط ورودی دارند و خروجی آنها از نوع void
است.
Action<int, int> printSum = (a, b) => Console.WriteLine(a + b);
printSum(3, 4); // خروجی: 7
در این مثال، یک Action تعریف شده که دو ورودی از نوع int
دارد و مجموع آنها را چاپ میکند. این Action خروجی ندارد، زیرا نوع خروجی آن void
است.
Func در سیشارپ
Func مشابه Action است، با این تفاوت که دارای خروجی است. آخرین پارامتر در Func همیشه نوع خروجی را مشخص میکند و میتواند تا 16 ورودی داشته باشد.
Func<int, int, int> sum = (a, b) => a + b;
Console.WriteLine(sum(3, 4)); // خروجی: 7
در اینجا، یک Func تعریف شده که دو ورودی عدد صحیح دریافت کرده و یک عدد صحیح به عنوان خروجی برمیگرداند.
استفاده از Predicate
Predicate یک نوع Delegate دیگر در سیشارپ است که یک ورودی دریافت کرده و یک مقدار بولین (bool
) بازمیگرداند. از Predicate برای سنجش شرایط خاص استفاده میشود.
Predicate<int> isEven = x => x % 2 == 0;
Console.WriteLine(isEven(4)); // خروجی: True
مزایای استفاده از Func و Action
استفاده از Func و Action مزایای متعددی دارد:
کاهش کدنویسی: با استفاده از این Delegateها نیازی به تعریف Delegateهای سفارشی ندارید و میتوانید از Delegateهای عمومی استفاده کنید.
انعطافپذیری: این Delegateها برای متدهایی با امضاهای مختلف قابل استفاده هستند.
سادگی و خوانایی بیشتر: استفاده از Func و Action کد شما را سادهتر و خواناتر میکند، چرا که نیازی به تعریف Delegateهای خاص ندارید.
مثال عملی از استفاده ترکیبی از Delegate، Func و Action
فرض کنید برنامهای دارید که چند عملیات ریاضی مختلف را اجرا میکند و کاربر باید نوع عملیات را انتخاب کند:
public class Program
{
public static void Main()
{
Func<int, int, int> operation;
Console.WriteLine("نوع عملیات را انتخاب کنید: 1- جمع 2- تفریق 3- ضرب");
string choice = Console.ReadLine();
if (choice == "1")
{
operation = (a, b) => a + b;
}
else if (choice == "2")
{
operation = (a, b) => a - b;
}
else if (choice == "3")
{
operation = (a, b) => a * b;
}
else
{
Console.WriteLine("گزینه نامعتبر است.");
return;
}
Console.WriteLine("نتیجه: " + operation(10, 5));
}
}
در این مثال، بسته به انتخاب کاربر، یکی از عملیات جمع، تفریق یا ضرب به Delegate operation
مرتبط شده و سپس اجرا میشود.
جمعبندی
Delegate یکی از مفاهیم قدرتمند در سیشارپ است که به شما اجازه میدهد به متدها اشاره کرده و آنها را بهصورت غیرمستقیم فراخوانی کنید. این ویژگی بهخصوص در مواقعی که نیاز به اجرای پویا و انعطافپذیر متدها دارید بسیار مفید است. همچنین با استفاده از Delegateهای عمومی مانند Func، Action و Predicate، میتوانید از قدرت Delegateها با سادگی و کارایی بیشتری بهرهمند شوید.
این ابزارها به شما کمک میکنند تا برنامههایی قابل انعطافتر، خواناتر و سادهتر بنویسید که در پروژههای بزرگ بسیار ارزشمند است. امیدواریم این مقاله توانسته باشد مفهوم Delegate و کاربردهای آن را به خوبی توضیح دهد و شما را در استفاده بهتر از این ویژگیها یاری کند.
برای افزودن دیدگاه خود، نیاز است ابتدا وارد حساب کاربریتان شوید