מה זה Delegates?
מצביע לפונקציה שהיא Type safe.
משתנה מוגדר כ-Delegate, הוא משתנה מסוג reference שיכול להחזיר reference לפונקציה. כדי שהמשתנה יחזיר reference לפונקציה מסויימת, חייבים להיות לו פרמטרים עם סוגים שמתאימים לפונקציה המתאימה וערך מוחזר שמתאים לערך שהפונקציה מחזירה.
אפשר להתאים כל פונקציה עם אותם פרמטרים ואותו סוג מוחזר למשתנה ה-delegate שמגדירים ואפשר לקרוא לפונקציה דרך המופע של המשתנה.
נראה דוגמא לשימוש ב-delegate עם פונקציה סטטית.
הגדרת delegate
נניח שאנחנו רוצים פונקציונליות שמוציאה טקסט עם זמן עליו. נרצה את האפשרות לשלוח את הטקסט למסך או לקובץ טקסט.
class Program
{
delegate void LogDel(string text);
static void Main(string[] args)
{
LogDel logDel = new LogDel(LogTextToScreen);
logDel("some text");
Console.ReadKey();
}
static void LogTextToScreen(string text)
{
Console.WriteLine($"{DateTime.Now}: {text}");
}
}
יש לנו הגדרה של פונקציית LogTextToScreen שהחתימה שלה היא void ומקבלת פרמטר string.
יש לנו הגדרה של delegate עם אותה החתימה של הפונקציה. אנחנו מעבירים את הפונקציה כמשתנה ל-delegate שיצרנו ועכשיו אפשר לקרוא לפונקציה דרך ה-delegate עצמו עם העברת הפרמטר שלה.
הוספת פונקציה ל-delegate
נניח שיש לנו דרישה להדפיס את הלוג לקובץ טקסט. נוסיף פונקציה שמבצעת את זה.
static void LogTextToFile(string text)
{
using (StreamWriter sw = new StreamWriter(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log.txt"), true)) {
sw.WriteLine($"{DateTime.Now}: {text}");
}
}
נחליף את הפונקציה של logDel בפונקציה החדשה.
static void Main(string[] args)
{
LogDel logDel = new LogDel(LogTextToFile);
Console.WriteLine("Enter you name: ");
var name = Console.ReadLine();
logDel(name);
Console.ReadKey();
}
נראה שנוצר לנו קובץ בתיקייה ממנה פועלת התוכנית עם המידע שהכנסנו אליו.
הפעלת delegate מתוך class
ניתור מחלקה בשם log ונעביר אליה את הפונקצייות שלנו.
class Log
{
public void LogTextToScreen(string text)
{
Console.WriteLine($"{DateTime.Now}: {text}");
}
public void LogTextToFile(string text)
{
using (StreamWriter sw = new StreamWriter(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log.txt"), true)) {
sw.WriteLine($"{DateTime.Now}: {text}");
}
}
}
בפונקציה הראשית ניצור מופע של ה-class ונעביר ל-logDel את הפונקציה מתוך ה-class.
static void Main(string[] args)
{
Log log = new Log();
LogDel logDel = new LogDel(log.LogTextToScreen);
Console.WriteLine("Enter you name: ");
var name = Console.ReadLine();
logDel(name);
Console.ReadKey();
}
הקוד עובד כמצופה.
Multicast Delegate
אפשר לחבר יותר מפונקציה אחת ל-delegate. ניצור delegate לכל פונקציה ונחבר אותן ל-delegate אחד. עכשיו אפשר לקרוא דרך ה-delegate המשותף לשתי הפונקציות ביחד.
static void Main(string[] args)
{
Log log = new Log();
LogDel logTextToScreenDel, logTextToFileDel;
logTextToScreenDel = new LogDel(log.LogTextToScreen);
logTextToFileDel = new LogDel(log.LogTextToFile);
LogDel multiLogDel = logTextToScreenDel + logTextToFileDel;
Console.WriteLine("Enter you name: ");
var name = Console.ReadLine();
multiLogDel(name);
Console.ReadKey();
}
שליחת delegate לפונקציה
גם את delegate אפשר לשלוח לפונקציה. בדוגמא שלחתי את multiLogDel אבל אפשר גם לשלוח את logTextToScreenDel או logTextToFileDel.
static void LogText(LogDel logDel, string text)
{
logDel(text);
}
קריאה לפונקציה.
LogText(multiLogDel, name);