41. Anonymous delegates

אחת ההמצאות היפות בC# היא הdelegateים.

מדובר במצביע לפונקציה, כלומר טיפוס שמאפשר להכניס פונקציה למשתנה.

אחד הדברים המגניבים שאפשר לעשות עם delegateים הוא ליצור פונקציות שמקבלות delegate ומשתמשות בו.

למשל, אנחנו יכולים לכתוב delegate כזה

1
public delegate bool Predicate<T>(T item);

זהו delegate שמקבל באופן איבר מטיפוס T ובודק אם חל עליו תנאי.

כעת נוכל לכתוב פונקציה כזאת:

1
2
3
4
5
6
7
8
9
10
11
12
13
public static T First<T>(IEnumerable<T> enumerable,
Predicate<T> condition)
{
foreach (T currentItem in enumerable)
{
if (condition(currentItem))
{
return currentItem;
}
}
return default(T);
}

זו פונקציה שמקבלת אוסף של איברים ופרדיקט, ומוצאת את האיבר הראשון באוסף שחל עליו התנאי.

נוכל לקרוא לה לדוגמה כך:

ניצור פונקציה עם חתימה של הפרדיקט

1
2
3
4
public static bool IsOdd(int number)
{
return (number%2 != 0);
}

ניצור אוסף:

1
int[] numbers = {4,8,15,16,23,42};

ונקרא לה:

1
Console.WriteLine(First(numbers, IsOdd)); // Prints 15

יפה, לא?

מה הבעיה?

הבעיה היא שכעת בשביל כל קריאה לפונקציה, נצטרך לכתוב פונקציה טיפשית כזאת (לפעמים לאו דווקא טיפשית, וכדאי לכתוב פונקציה כזאת אם היא מורכבת ובעלת לוגיקה מסובכת)

אז בC# 2.0 באו והחליטו שיאפשרו לנו לעשות משהו כזה בלי לכתוב פונקציה:

לזה קוראים Anonymous delegates.

נוכל לבצע בדיוק מה שעשינו קודם, רק כך:

1
2
3
Console.WriteLine(First(numbers,
delegate(int number)
{ return (number % 2 == 0); })); // Prints 15

למי שמעדיף, אפשר גם להכניס למשתנה קודם:

1
2
3
4
5
Predicate<int> isOdd =
delegate(int number)
{ return (number%2 == 0); };
Console.WriteLine(First(numbers, isOdd)); // Prints 15

יתרונות:

  1. חסכנו הרבה מתודות קטנות ומיותרות
  2. זה כלי מאוד חזק, ואנחנו נראה את זה בהמשך

חסרונות:

  1. זה לא הכי קריא בעולם
  2. ברגע שכתבנו דבר כזה במתודה, לא נוכל לשנות את המתודה שכתבנו את זה בה בזמן דיבוג (Edit and continue)

שבוע אנונימי טוב

שתף