חבר בעבודה שאל אותי השבוע: מה זה Func?
אז בשביל להסביר לו, עניתי לו שזה פשוט צורה יותר קלה להגדרת Delegate.
אז נתחיל מההתחלה: מה זה Delegate?
Delegate זה אובייקט Reference שמצביע לפונקציה.היתרון בשימוש ב Delegate זה שצד שלישי יכול להגדיר איזה פונקציה הוא בדיוק רוצה שתופעל, והמימוש שלנו לא יהיה תלוי בכך.
הגדרת Delegate:
הגדרת ה Delegate תהיה תחת ה namespace שלנו, ולא תחת Class מסוים. לדוגמא:
מה הגדרנו כאן: הגדרנו שה Delegate שלנו יכול להצביע לכל פונקציה שהחתימה שלה: מחזירה Void ומקבלת String.
נאמר שיש לנו בתוכנית את שתי הפונקציות הנ"ל:
לאחר שנריץ את הקוד הבא:
נקבל:
Eyal is in PrintOne Function
בשורה מספר 3 הגדרנו שה Delegate שלנו יצביע לפונקציה PrintOne, ובשורה 5 פשוט קראנו לDelegate שלנו בדיוק כמו שהיינו קוראים אם היינו קוראים לפונקציה.
Multycast Delegate
Delegate יכול להצביע גם על מספר פונקציות (נקרא Multycast Delegate). וכאשר "מפעילים" את ה Delegate, הוא יקרא לפונקציות בסדר שהם נרשמו. את הרישום נעשה באמצעות אופרטור =+
למשל:
ונקבל:
Eyal is in PrintOne Function
Eyal is in PrintTwo Function
Closure
שימוש נפוץ ל Delegate הוא ביצוע Closure, כלומר העברת פונקציה כפרמטר.
נניח ויש לנו את הפונקציה הנ"ל:
הפונקציה מקבלת כפרמטר Delegate ומפעילה אותו.
ואז בתכנית שלנו פשוט נוכל לאתחל את ה Delegate עם הפונקציה שאנו רוצים לשלוח, וכך להפעיל את הפונקציה:
ונקבל:
MyPrintMethod is in PrintTwo Function
Generic Delegate
אנחנו יכולים גם להגדיר שה Delegate שלנו יהיה גנרי, ואז לא נצטרך לרשום Delegate שונים עבור פונקציות שמקבלות Type שונים:
לשם ההדגמה נניח ויש לנו פונקציית הדפסה חדשה:
עכשיו תחת ה namespace נגדיר את ה Delegate הגנרי הבא:
וכעת נוכל להשתמש עם אותו ה Delegate שיצביע על פונקציות עם חתימות שונות:
ונקבל:
Eyal is in PrintTwo Function
<Action<T
יופי, אז ראינו שימושים שונים ל Delegate.
אבל זה קצת מסורבל, לא?
החל מ NET 2.0 קיבלנו את Action, שזהו פשוט סוג של Delegate, שיודע לקבל עד 16 פרמטרים, ומחזיר void. השימוש ב Action מקל לנו על כתיבת הקוד.
תראו איזה פשוט נהיה השימוש ב Delegate, באמצעות Action:
אין צורך להגדיר Delegate ב namespace, אלא פשוט יוצרים Action, ונותנים לו הצבעה לפונקציה:
ונקבל:
action is in PrintTwo Function
ונראה איזה פשוט זה לשלוח פונקציה כפרמטר באמצעות Action (ביצוע Closure):
נניח ויש לנו את הפונקציה:
נפעיל את הקריאה ע"י:
ונקבל:
MyPrintMethodAction is in PrintTwo Function
<Func<T,Result
ולשאלתנו, מה זה Func? זה פשוט כל מה ש Action, רק ש Func מחזיר פרמטר.
יש לנו לדוגמא את הפונקציה הפשוטה הבאה שמקבלת פרמטר מסוג int, ומחזירה int:
נשתמש עם ה Delegate הבא:
ונקבל: 8
שימו לב שב Func, הפרמטר הגנרי האחרון יהיה הטיפוס שאנחנו מחזירים. מכיוון ש Func תמיד מחזיר ערך אז Func T לא מקבל שום פרמטר, אך מחזיר פרמטר מסוג T.
תהנו!!
אז בשביל להסביר לו, עניתי לו שזה פשוט צורה יותר קלה להגדרת Delegate.
אז נתחיל מההתחלה: מה זה Delegate?
Delegate זה אובייקט Reference שמצביע לפונקציה.היתרון בשימוש ב Delegate זה שצד שלישי יכול להגדיר איזה פונקציה הוא בדיוק רוצה שתופעל, והמימוש שלנו לא יהיה תלוי בכך.
הגדרת Delegate:
הגדרת ה Delegate תהיה תחת ה namespace שלנו, ולא תחת Class מסוים. לדוגמא:
delegate void PrintDelegate(string st);
מה הגדרנו כאן: הגדרנו שה Delegate שלנו יכול להצביע לכל פונקציה שהחתימה שלה: מחזירה Void ומקבלת String.
נאמר שיש לנו בתוכנית את שתי הפונקציות הנ"ל:
static void PrintOne(string st)
{
System.Console.WriteLine("{0} is in PrintOne Function", st);
}
static void PrintTwo(string st)
{
System.Console.WriteLine("{0} is in PrintTwo Function", st);
}
static void Main(string[] args)
{
PrintDelegate p = new PrintDelegate(PrintOne);
p("Eyal");
}
Eyal is in PrintOne Function
בשורה מספר 3 הגדרנו שה Delegate שלנו יצביע לפונקציה PrintOne, ובשורה 5 פשוט קראנו לDelegate שלנו בדיוק כמו שהיינו קוראים אם היינו קוראים לפונקציה.
Multycast Delegate
Delegate יכול להצביע גם על מספר פונקציות (נקרא Multycast Delegate). וכאשר "מפעילים" את ה Delegate, הוא יקרא לפונקציות בסדר שהם נרשמו. את הרישום נעשה באמצעות אופרטור =+
למשל:
static void Main(string[] args)
{
PrintDelegate p = new PrintDelegate(PrintOne);
p += PrintTwo;
p("Eyal");
}
ונקבל:
Eyal is in PrintOne Function
Eyal is in PrintTwo Function
Closure
שימוש נפוץ ל Delegate הוא ביצוע Closure, כלומר העברת פונקציה כפרמטר.
נניח ויש לנו את הפונקציה הנ"ל:
static void MyPrintMethod(PrintDelegate p)
{
p("MyPrintMethod");
}
ואז בתכנית שלנו פשוט נוכל לאתחל את ה Delegate עם הפונקציה שאנו רוצים לשלוח, וכך להפעיל את הפונקציה:
MyPrintMethod(new PrintDelegate(PrintTwo));
ונקבל:
MyPrintMethod is in PrintTwo Function
Generic Delegate
אנחנו יכולים גם להגדיר שה Delegate שלנו יהיה גנרי, ואז לא נצטרך לרשום Delegate שונים עבור פונקציות שמקבלות Type שונים:
לשם ההדגמה נניח ויש לנו פונקציית הדפסה חדשה:
static void PrintThree(int num)
{
System.Console.WriteLine("{0} is in PrintThree Function", num);
}
עכשיו תחת ה namespace נגדיר את ה Delegate הגנרי הבא:
delegate void PrintGenericDelegate(T t);
וכעת נוכל להשתמש עם אותו ה Delegate שיצביע על פונקציות עם חתימות שונות:
PrintGenericDelegate<string> pgs = new PrintGenericDelegate<string>(PrintTwo);
pgs("Eyal");
PrintGenericDelegate<int> pgi = new PrintGenericDelegate<int>(PrintThree);
pgi(111);
Eyal is in PrintTwo Function
111 is in PrintThree Function
<Action<T
יופי, אז ראינו שימושים שונים ל Delegate.
אבל זה קצת מסורבל, לא?
החל מ NET 2.0 קיבלנו את Action, שזהו פשוט סוג של Delegate, שיודע לקבל עד 16 פרמטרים, ומחזיר void. השימוש ב Action מקל לנו על כתיבת הקוד.
תראו איזה פשוט נהיה השימוש ב Delegate, באמצעות Action:
אין צורך להגדיר Delegate ב namespace, אלא פשוט יוצרים Action, ונותנים לו הצבעה לפונקציה:
Action<string> MyAction = PrintTwo;
MyAction("action");
ונקבל:
action is in PrintTwo Function
ונראה איזה פשוט זה לשלוח פונקציה כפרמטר באמצעות Action (ביצוע Closure):
נניח ויש לנו את הפונקציה:
static void MyPrintMethodAction(Action<string> action)
{
action("MyPrintMethodAction");
}
נפעיל את הקריאה ע"י:
Action<string> MyAction = PrintTwo; MyPrintMethodAction(MyAction);
ונקבל:
MyPrintMethodAction is in PrintTwo Function
<Func<T,Result
ולשאלתנו, מה זה Func? זה פשוט כל מה ש Action, רק ש Func מחזיר פרמטר.
יש לנו לדוגמא את הפונקציה הפשוטה הבאה שמקבלת פרמטר מסוג int, ומחזירה int:
static int MultiplyTwice(int num)
{
return num * 2;
}
נשתמש עם ה Delegate הבא:
Func<int,int> MyFunc = MultiplyTwice; Console.WriteLine(MyFunc(4));
ונקבל: 8
שימו לב שב Func, הפרמטר הגנרי האחרון יהיה הטיפוס שאנחנו מחזירים. מכיוון ש Func תמיד מחזיר ערך אז Func T לא מקבל שום פרמטר, אך מחזיר פרמטר מסוג T.
תהנו!!
אין תגובות:
הוסף רשומת תגובה