קהל יעד
תוכניתני C# 2 העובדים ב-Generics
וכן מכירים מספיק טוב שימוש ב-delegates ומעוניינים לבחון את האפשרות לעבור ל-C# 3, או
כאלה שכבר עובדים ב-C# 3 ואוהבים לקרוא בנושא.
כללי
Lambda Expression היא יכולת מסוימת שאם ננסה להסבירה בצורה פשוטה, נגדיר
זאת כך: היכולת שלנו לכתוב Anonymous
Delegates/Methods בצורה פשוטה יותר.
Anonymous Methods?
נניח שאנו קולטים ב-Console Application
מספרים מהמשתמש לתוך מערך של string. לאחר שקלטנו מערך של מחרוזות (strings), אנו
נרצה להמיר אותם למספרים. דרך אחת, היא באמצעות foreach:
// input in string format
string[] input = new string[] { "1", "2", "3", "4", "5", "6" };
// convert to int typed list
List<int> list = new List<int>();
foreach (string s in input)
list.Add(int.Parse(s));
// to array...
int[] result = list.ToArray();
דרך נוספת, היא
להשתמש ב- Array.ConvertAll<
>:
// input in string format
string[] input = new string[] { "1", "2", "3", "4", "5", "6" };
// to array...
int[] result = Array.ConvertAll<string, int>(input, MyConvert);
private static int MyConvert(string s)
{
return int.Parse(s);
}
Array.ConvertAll< >
סה"כ מבצע בדיוק את מה שעשינו קודם לכן: foreach
וקריאה ל-MyConvert, היא הפונקציה שלנו, המתרגמת מחרוזת בודדת ל-int. קצת
מסורבל. כתבנו פונקציה "שלמה" לטובת מטרה פשוטה: לבצע int.Parse.
באמצעות Anonymous Method אפשר
לפשט את הדברים:
// input in string format
string[] input = new
string[] { "1",
"2", "3",
"4", "5",
"6" };
// to array...
int[] result = Array.ConvertAll<string, int>(input,
delegate(string
s)
{
return int.Parse(s);
});
למעשה, שמנו את גוף
הפונקציה MyConvert ישירות בתור ארגומנט ל-Array.ConvertAll< >. אם
נסדר קצת את הקוד ונצמצם שורות מיותרות, נגיע לתוצאה הבאה:
int[] result = Array.ConvertAll<string, int>(input,
delegate(string
s) { return int.Parse(s);
});
זה כבר יותר נחמד. קצר, ברור למדי וכאשר מתרגלים – ברור מאוד. כדאי
לשים לב שאין צורך לציין את ערך ההחזר של ה-delegate (במקרה זה: int), כיוון שהקומפיילר כבר מסיק זאת בעצמו.
Lambda Expressions
באמצעות C# 3, ניתן
לכתוב Lambda Expressions אשר יפשטו עוד יותר את הדברים. לפני שרצים לקוד,
כדאי להקדים ולומר, שהקומפיילר הולך ונהיה יותר ויותר "חכם". למעשה, הוא
כ"כ חכם, שהוא פשוט מסיק הרבה דברים לבד. בדוגמא הקודמת, הקומפיילר הסיק בעצמו
שערך ההחזר הוא מסוג int (לפי ה-Converter
delegate וה-generics
שצוינו). הקומפיילר נהיה עוד יותר "חכם" בגרסה 3, ולכן מתאפשרת הפשטה של
הקוד. אנו נדגים זאת בשלבים:
- השלב הראשון
דווקא לא קשור ל-lambda
expression. הקומפיילר לבדו מבין
שמדובר ב-string input ו-int output, שכן הוא מבחין בסוגי
הפרמטרים הנדרשים. לכן, ניתן להוריד את ההגדרות המפורשות:
int[] result = Array.ConvertAll<string, int>(input,
delegate(string
s) { return int.Parse(s);
});
- ברור לקומפיילר
שמדובר ב-delegate. הוא מסיק זאת לפי הארגומנט המופיע בחתימה של Array.ConvertAll< >. לכן ניתן להשמיט את המילה המיותרת:
int[] result = Array.ConvertAll(input,
delegate(string
s) { return int.Parse(s);
});
- בצורה דומה,
אפשר להשמיט את ה-string בארגומנט של ה-delegate,
כיוון שהקומפיילר מסיק זאת לפי העובדה ש-input
הוא מערך של מחרוזות:
int[] result = Array.ConvertAll(input,
(string s) { return int.Parse(s);
});
- העובדה שמדובר
ב-delegate שמחזיר ערך, ברורה לקומפיילר מהחתימה של Converter delegate
(בדיוק כפי שהוא הסיק שמדובר בערך החזר מסוג int).
לכן גם המילה return מיותרת:
int[] result = Array.ConvertAll(input,
(s) { return int.Parse(s); });
- מה שנשאר הוא
ארגומנט s וגוף הפונקציה:
int[] result = Array.ConvertAll(input,
(s) { int.Parse(s); });
- במטרה להשמיט
את הסוגריים המיותרים הן מהארגומנט והן מגוף הפונקציה, C# 3
מספק לנו אופרטור חדש. התוצאה, קרויה lambda expression:
int[] result = Array.ConvertAll(input,
s => int.Parse(s));
- בהשוואה אל מול
ה-anonymous delegate שכתבנו קודם (ללא ה-generics):
int[] result = Array.ConvertAll(input,
delegate(string
s) { return int.Parse(s);
});
אל מול:
int[] result = Array.ConvertAll(input,
s => int.Parse(s));
כאשר מבינים lambda
expression כהפשטה של Anonymous Method, כאשר צד שמאל של האופרטור <= הוא הארגומנט, וצד ימין הוא גוף הפונקציה, הדברים
ברורים למדי. מה שנשאר הוא לתרגל ולהפנים.
סיכום
Lambda Expressions היא דרך שבה אנחנו יכולים לפשט ולייעל את השימוש ב-Anonymous Methods.
כתוצאה מהשימוש הזה, לומדים מהר מאוד כיצד לקצר את הקוד שלנו ועדיין להשאיר אותו
קריא. בשילוב עם LINQ, אפשר להגיע לתוצאות נהדרות בקוד.
מה צריך בשביל זה?
.NET Framework 3.5 ו-Visual Studio 2008 או
מאוחר יותר.
קישורים נוספים
Anonymous Methods
Lambda Expressions
C# 3.0
and LINQ - Expression Trees
Currently rated 4.6 by 7 people
- Currently 4.571429/5 Stars.
- 1
- 2
- 3
- 4
- 5