תכנות אסינכרוני, תקשורת ופיתוח אפליקציות ל- Windows 8.1 ואפליקציות ל- Windows Phone 8 שיפורים בשפת C# C# Evolution מאז הגרסה הראשונה של C# התווספו לה יכולות רבות. על מנת להכיר את היכולות האסינכרוניות החדשות של C# 5 צריך להכיר מקצת מהשיפורים בשפה. Generics Genericsשהוצגו בגרסה C# 2.0הם הרחבה רבת עוצמה של השפה. מאפשרת להגדיר אוספים ,מחלקות ,מבנים ,מתודות מבלי להתחייב על הטיפוס בזמן כתיבה. יתרונות: – Type-Safe בזמן ההקצאה הקומפיילר יודע בדיוק מה הטיפוס (לא יתכן מצב של ”)1,2,”3 מפחית את השימוש ב Boxing -ו.Unboxing- שיפור גדול בביצועים. שימוש חוזר באלגוריתמים (חיפוש ,מיון.).... תחביר כללי: שימוש ב <T> -להגדרת טיפוס גנרי אשר יוגדר בזמן ריצה. Generics Object -> Reference Type Int32 -> Value Type .Reference Type - לValue Type המרה בין- Boxing Value - לReference Type – המרה ביןUnboxing .Type . מוגדר בזמן כתיבה ולא בזמן ריצהT – Type Safe public class Stack { object[] m_Items; public void Push(object item) {...} public object Pop() {...} } public class Stack<T> { T[] m_Items; public void Push(T item) {...} public T Pop() {...} } Stack<int> stack = new Stack<int>(); stack.Push(1); stack.Push(2); int number = stack.Pop(); :Generics לפני :Generics עם Generics :דוגמה נוספת :Generics עם public struct Point<T> { public T X; public T Y; } Point<int> point; point.X = 1; point.Y = 2; Point<double> point; point.X = 1.2; point.Y = 3.4; :Generics לפני public struct PointInt { public int X; public int Y; } public struct PointDouble { public double X; public double Y; } public struct Point { public object X; public object Y; } :או לחילופין Generics List<int> arr1 = new List<int>(); arr1.Add(100); arr1.Add(200); arr1.Add(300); arr1.Add(400); arr1.Add(500); :List - שימושים List<Person> arr2 = new List<Person>(); arr2.Add(new Person("Elimelech", "Zorkin",65,123456)); arr2.Add(new Person("Zelda","Gurnisht",44,4545454)); arr2.Add(new Person("Zrubavel","Berkovitch",32,8854646)); arr2.Add(new Person("Vladimir","Swisa",12,3434843)); ListSample :דוגמת קוד GenericListSample :דוגמת קוד Generics class MyGenericArray<T> { private T[] m_Arr; private int m_Counter; public MyGenericArray() { m_Arr = new T[16]; } public void Add(T t) { if (m_Counter >= m_Arr.Length) Array.Resize(ref m_Arr, m_Arr.Length + 16); m_Arr[m_Counter++] = t; } public T this[int index] { get { return m_Arr[index]; } } public void Print() { for (int i = 0; i < m_Counter; i++) { Console.WriteLine(m_Arr[i]); } } } :שימושים – יצירת רשימות מותאמות static void Main(string[] args) { MyGenericArray<int> arr1 = new MyGenericArray<int>(); arr1.Add(100); arr1.Add(200); arr1.Add(300); arr1.Add(400); arr1.Add(500); arr1.Print(); MyGenericArray<Person> arr2 = new MyGenericArray<Person>(); arr2.Add(new Person("Elimelech", "Zorkin",65,123456)); arr2.Add(new Person("Zelda","Gurnisht",44,4545454)); arr2.Add(new Person("Zrubavel","Berkovitch",32,8854646)); arr2.Add(new Person("Vladimir","Swisa",12,3434843)); arr2.Print(); } GenericSample01 :דוגמת קוד Generics static void Swap<T>(ref T t1, ref T t2) { T tmp = t1; t1 = t2; t2 = tmp; } static void Main(string[] args) { int num1 = 11; int num2 = 22; Console.WriteLine("num1={0}, num2={1}", num1, num2); Swap(ref num1, ref num2); Console.WriteLine("num1={0}, num2={1}", num1, num2); } :שימושים – מתודות גנריות string str1 = "Elchanan"; string str2 = "Sonya"; Console.WriteLine("str1={0}, str2={1}", str1, str2); Swap(ref str1, ref str2); Console.WriteLine("str1={0}, str2={1}", str1, str2); GenericMethod :דוגמת קוד Generics class MyGenericList<T>:List<T> { public void Print() { for (int i = 0; i < base.Count; i++) { Console.WriteLine(base[i]); } } } הרחבת היכולות List של :List שימושים – הורשה של static void Main(string[] args) { MyGenericList<string> arr1 = new MyGenericList<string>(); arr1.Add("Shoshana"); arr1.Add("Yerachmiel"); arr1.Add("Zelda"); arr1.Add("Pirchiya"); arr1.Add("Zalman"); arr1.Add("Fruma"); arr1.Print(); } GenericMethod :דוגמת קוד Generics interface IMyInterface<T> { void Print(); } class Person : IMyInterface<Person> { … } class MyGenericArray<T> { private T[] m_Arr; private int m_Counter; … } static void Main(string[] args) { MyGenericArray<Person> arr1 = new MyGenericArray<Person>(); arr1.Add(new Person("Elimelech", "Zorkin", 65)); arr1.Add(new Person("Zelda", "Gurnisht", 44)); arr1.Add(new Person("Muhamad", "Berkovitch", 32)); arr1.Add(new Person("Vladimir", "Swisa", 12)); arr1.PrintAll(); } :שימושים – ממשקים Generics public delegate void ChangeDelegate<T>(T t); class Person { private string m_FirstName; private string m_LastName; private int m_Age; public event ChangeDelegate<string> FirstNameChangeNotify; public event ChangeDelegate<string> LastNameChangeNotify; public event ChangeDelegate<int> AgeChangeNotify; . . . public string FirstName { get { return m_FirstName; } set { if (value != m_FirstName) { m_FirstName = value; FirstNameChangeNotify(m_FirstName); } } } } Delegate הגדרת גנרי :Delegate – שימושים Event הגדרת Event הפעלת GenericDelegate :דוגמת קוד Generics static void Main(string[] args) { ChangeDelegate<Person> del = new ChangeDelegate<Person>(Program.Func); Person p = new Person("Isaschar", "Shemyafe", 78); p.LastNameChangeNotify += LastNameChangeNotify; p.FirstNameChangeNotify += FirstNameChangeNotify; p.AgeChangeNotify += AgeChangeNotify; p.LastName = "Havakook"; p.LastName = "Loshemyafe"; p.Age = 100; del(p); } : המשךDelegate – שימושים Event-רישום ל static void AgeChangeNotify(int t) { Console.WriteLine("New Age: " + t); } GenericDelegate :דוגמת קוד Generics אילוצים ()Generic Type Constraint לכל פריט גנרי יש לפחות פרמטר גנרי אחד אשר צריך לספק בזמן ריצה. .NETמאפשרת להגדיר אילוצים המגבילים את בחירת הטיפוסים בזמן ריצה. האילוצים נבדקים בזמן קומפילציה ,אם נחרוג מהמוגדר נקבל שגיאה. רשימת אילוצים: where T : structהטיפוס חייב להיות . ValueType where T : classהטיפוס חייב להיות .Reference Type where T : BaseClassהטיפוס חייב להיות מחלקת בסיס או אחת מניגזרותיה. where T : IInterfaceהטיפוס חייב לממש את הממשק .IInterface )( where T : newלטיפוס חייב להיות .Default Ctor Generics static void Swap<T>(ref T t1, ref T t2) where T:struct אילוצים { T tmp = t1; t1 = t2; t2 = tmp; } int num1 = 11; int num2 = 22; static void Swap2<T>(ref T t1, ref T t2) where T : IMyInterface Swap(ref num1, ref num2); { Other o1 = new Other(); T tmp = t1; Other o2 = new Other(); t1 = t2; Swap(ref o1, ref o2); t2 = tmp; } class IMyInterface { } class MyClass : IMyInterface { } GenericConstraints01 :דוגמת קוד int num1 = 11; int num2 = 22; MyClass c1 = new MyClass(); MyClass c2 = new MyClass(); Swap2(ref c1, ref c2); Swap2(ref num1, ref num2); Generics אילוצים class MyGenericArray1<T> where T: class { private T[] m_Arr; private int m_Counter; …. } class Base { } class Derived : Base { } class Other { } struct Point { } MyGenericArray1<Derived> arr1 = new MyGenericArray1<Derived>(); MyGenericArray1<Point> arr2 = new MyGenericArray1<Point>(); GenericConstraints01 :דוגמת קוד Implicit Typing - Var Beginning in Visual C# 3.0, variables that are declared at method scope can have an implicit type var. An implicitly typed local variable is strongly typed just as if you had declared the type yourself, but the compiler determines the type. The following two declarations of i are functionally equivalent: var i = depyt ylticilpxe// ;10 = i tni depyt ylticilpmi // ;10 Local variables can be given an inferred "type" of var instead of an explicit type. The var keyword instructs the compiler to infer the type of the variable from the expression on the right side of the initialization statement. The inferred type may be a built-in type, an anonymous type, a user-defined type, or a type defined in the .NET Framework class library. For more information about how to initialize arrays with var, see Implicitly Typed Arrays (C# Programming Guide). The following examples show various ways in which local variables can be declared with var: var i = ;"olleH" = s rav gnirts a sa delipmoc si s // ;5 It is important to understand that the var keyword does not mean "variant" and does not indicate that the variable is loosely typed, or late-bound. It just means that the compiler determines and assigns the most appropriate type. The var keyword may be used in the following contexts: On local variables (variables declared at method scope) as shown in the previous example. In a for initialization statement. foreach(var item in list }...{) Anonymous Methods :delegate רישום והפעלה של,דוגמת קוד הפשוטה הבאה מציגה הגדרה הגדרה delegate void MyDelgate(); class Program { static void Main(string[] args) { MyDelgate my_delegate = new MyDelgate(Func); my_delegate(); } הפעלה public static void Func() { Console.WriteLine("Delegate Invoked"); } } רישום יכולה להיקרא על ידיDelegate - שנועדה להיקרא על ידי הFunc למעשה המתודה- הבעיה .כל חלק אחר של התוכנית מבלי שיוצריה התכוונו לכך Anonymous Methods החל מ C# -גרסה 2.0ניתן לחבר ישירות בין ה Delegate -לבין קטע הקוד אשר אמור להתבצע כאשר הוא מופעל: הגדרה רישום לא צריך להגדיר מתודה בצורה מפורשת אלא כותבים מקטע קוד אשר ירוץ בכל פעם שהDelegate- הקומפיילר כבר יודע לייצר את המתודה בזמן קומפילציה. לא ניתן להפעיל את המימוש ללא ה.Delegate- ;)(delegate void MyDelgate class Program { יופעל, )static void Main(string[] args { )(MyDelgate my_delegate = delegate { ;)"Console.WriteLine("Delegate Invoked ;} ;)(my_delegate } הפעלה } Anonymous Methods :Event ועם הגדרה delegate void MyDelegate(string msg); class Program { public static event MyDelegate MyEvent; static void Main(string[] args) { MyEvent += delegate(string msg) { Console.WriteLine("msg : {0}",msg); }; MyEvent("Event Invoked"); } } אירוע רישום הפעלה Lambda Expression בגרסה Delegate C# 1.0קיבל כתובת של מתודה או של הרבה מתודות. בגרסה 2.0של C#התווספה לארסנל היכולות של השפה המתודה האנונימית ( )Anonymous Methodשאפשרה לחבר ישירות בין ה Delegate -לבין קטע הקוד אשר אמור להתבצע כאשר הוא מופעל. הגרסה השלישית של C#לוקחת אותנו עוד צעד קדימה ומאפשרת לממש את המתודה האנונימית באמצעות ביטוי למבדה (.)Lambda Expression ביטויי למבדה הם שיטה מאוד תמציתית לכתיבת מתודות אנונימיות על מנת לפשט את האופן בו אנו עובדים עם Delegateב.C# - השימוש בביטויי למבדה אינו מוסיף פונקציונאליות או יכולות שלא היו קיימות בגרסאות הקדומות יותר של .C# Lambda Expression ביטויי למבדה הם Inline Delegateאשר מציגים תחביר ייחודי לטובת מתודות אנונימיות. ביטויי למבדה הם פשוטים יותר לשימוש אבל דורשים להסתגל לתחביר שונה ממה שהכרנו עד כה. Parameters => Execution Code ביטוי למבדה מורכב משלושה חלקים: הפרמטרים של הביטוי, 0או יותר פרמטרים קוד לביצוע Lambda Operator לדוגמה: x => x * x הביטוי מקבל פרמטר בודד הנקרא ,Xהביטוי עצמו עושה שימוש בפרמטר. הטיפוס של Xמוגדר בצורה מרומזת ,אולם ניתן להגדירו בצורה מפורשת: ;(int x) => x * x לדוגמה: אין הבדל בין ההגדרות ,ממילא טיפוס הפרמטר מוכתב על ידי ה.Delegate - לאחר הלמבדה אופרטור (>=) נכתב הביטוי עצמו. ביטויי למבדה יכול לקבל מספר פרמטרים ,במקרה זה הפרמטרים חייבים להיות תחומים בסוגריים ,לדוגמה(n1,n2,n3)=>n1 + n2 + n3 : Lambda Expression המבנה התחבירי של ביטויי Lambda מבנה של משפט למבדה: params => expression – paramsרשימת פרמטרים שהביטוי מקבל ,אופציונאלי. <= -למבדה אופרטור ,סדר הקדימות שלו זהה לאופרטור השמה (=). – expressionהביטוי. לדוגמהx => x * x : הביטוי מקבל פרמטר בודד הנקרא ,Xהביטוי עצמו עושה שימוש בפרמטר. הטיפוס של Xמוגדר בצורה מרומזת ,אולם ניתן להגדירו בצורה מפורשת: ;(int x) => x * x לדוגמה: אין הבדל בין ההגדרות ,ממילא טיפוס הפרמטר מוכתב על ידי ה.Delegate - לאחר הלמבדה אופרטור (>=) נכתב הביטוי עצמו. ביטויי למבדה יכול לקבל מספר פרמטרים ,במקרה זה הפרמטרים חייבים להיות תחומים בסוגריים ,לדוגמה(n1,n2,n3)=>n1 + n2 + n3 : Lambda Expression delegate int MyDelegate(int i); Delegate הגדרת class Program { static void Main(string[] args) { השיטה הוותיקה // C# 1.0 - The traditional way MyDelegate del1 = new MyDelegate(Handler1); int result = del1(5); Console.WriteLine("C# 1.0 version - The traditional way : " + result); // C# 2.0 - With Anonymous Methods Anonymous MyDelegate del2 = delegate(int x) { return x * x; }; Methods result = del2(5); Console.WriteLine("C# 2.0 - With Anonymous Methods : " + result); // C# 3.0 - With Lambda Expression MyDelegate del = x => x * x; Lambda result = del(5); Console.WriteLine("C# 3.0 - With Lambda Expression :" + result); } שימו לב שאין התייחסות לערך המוחזר public static int Handler1(int x) , מחייב זאתDelegate -למרות שה { .החזרת הערך מתבצעת בצורה מרומזת return x * x; } LambdaExpressionSample01 :דוגמת קוד :דוגמה Lambda Expression : ביטוי למבדה שמקבל מספר פרמטרים,דוגמה public delegate int CalcSomething(int n1, int n2, int n3); class Program { static void Main(string[] args) { CalcSomething sum_del = (n1, n2, n3) => n1 + n2 + n3; CalcSomething mul_del = (n1, n2, n3) => n1 * n2 * n3; CalcSomething div_del = (n1, n2, n3) => n1 / n2 / n3; Console.WriteLine(sum_del(11, 22, 33)); Console.WriteLine(mul_del(2, 3, 4)); Console.WriteLine(div_del(1000, 10, 2)); } } LambdaExpressionSample02 :דוגמת קוד Delegate הגדרת Lambda Lambda Expression .ביטויי למבדה יכולים להכיל מספר משפטים או פקודות .במקרה זה הביטוי חייב להיות תחום בסוגריים מסולסלים ולכן ניתן להשתמש בכלNET Framework - וC# ביטויי למבדה הן חלק בלי נפרד משפת . בתוך ביטויי למבדהNET Framework -פקודות השפה ומחלקות המוגדרות ב public delegate void CalcSomething(int num1, int num, params int[] arr); … CalcSomething sum_del = (n1, n2, arr) => } int sum = n1 + n2; foreach (int n in arr) { sum += n; { return sum; {; … var result1 = sum_del(1, 2, 3, 4, 5, 6, 7); LambdaExpressionSample03 :דוגמת קוד Delegate הגדרת Lambda מפורשReturn Lambda Expression בעקבות הפיתוח של Genericsומהניסיון שהצטבר בשימוש בהם הבחינו מנהלי המוצר של .NET Frameworkשב 99.99%-מהמקרים אנחנו משתמשים רק בשלושה סוגים של :Delegate .1 Delegate - Predicateשמקבל פרמטר ומחזיר .bool .2 Delegate - Actionשמקבל בין 1-16פרמטרים ואינו מחזיר ערך. .3 Delegate - Funcשמקבל בין 1-16פרמטרים ומחזיר ערך. * הערה – השניים האחרונים "מועמסים" Lambda Expression Predicate Delegate ) public delegate bool Predicate<T>( T obj Delegateשמקבל פרמטר ומחזיר .bool מייצג מתודה הבודקת עם הפרמטר עומד בסדרה של קריטריונים. המתודה ) List<T>.FindAll(Predicate<T> matchבודקת אלו אובייקטים הנמצאים בList- עומדים בקריטריונים ומחזירה רשימה שלהם. היא עושה שימוש ב Predicate-כדי להגדיר את הקריטריונים לביצוע הבדיקה. Lambda Expression class Program { static void Main(string[] args) { List<int> list = new List<int> { 1, 43, 6, 12, 5, 23, 7, 86, 3, 49 }; // C# 1.0 style List<int> greater_than_10 = list.FindAll(new Predicate<int>(GreaterThanTen)); foreach (int num in greater_than_10) { Console.Write(num + ","); } Console.WriteLine(); // C# 2.0 style greater_than_10 = list.FindAll(delegate(int num) { return num > 10; }); foreach (int num in greater_than_10) { Console.Write(num + ","); } Console.WriteLine(); } LambdaExpressionSample04 :דוגמת קוד Predicate Delegate - דוגמת קוד // C# 3.0 style greater_than_10 = list.FindAll(num => num > 10); foreach (int num in greater_than_10) { Console.Write(num + ","); } Console.WriteLine(); } public static bool GreaterThanTen(int num) { return num > 10; } Lambda Expression Action Delegate public delegate void Action<T>( T obj ) .)Overloading( פרמטרים ואינו מחזיר ערך1-16 שמקבל ביןDelegate class Program { private static int result = 0; static void Main(string[] args) { Action<int, int> Sum = (n1, n2) => result = n1 + n2; Sum(11, 22); Console.WriteLine(result); -למבדה תוך שימוש ב Action Delegate string message1 = "The first line of a message."; string message2 = "The second line of a message."; string message3 = "The third line of a message."; Action<string, string, string> print = (s1, s2, s3) => WriteToConsole(s1, s2, s3); print(message1, message2, message3); } static void WriteToConsole(string string1, string string2, string string3) { Console.WriteLine("{0}\n{1}\n{2}", string1, string2, string3); } LambdaExpressionSample06 :דוגמת קוד . מייצג פעולה בלבד,כשמו כן הוא -למבדה תוך שימוש ב Action Delegate Lambda Expression Action Delegate List<T>.ForEach( Action<T> action) static void Main() { List<String> names = new List<String>() { "Elimelech", "Zrubavel", "Havakuk", "Yerachmiel" }; // C# 1.0 style names.ForEach(Print); // C# 2.0 style names.ForEach(delegate(String name) { Console.WriteLine(name); }); // C# 3.0 style names.ForEach(str=>Console.WriteLine(str)); } private static void Print(string s) { Console.WriteLine(s); } LambdaExpressionSample07 :דוגמת קוד Lambda Expression -למבדה תוך שימוש ב Func Delegate Func Delegate public delegate TResult Func<T, TResult>( T arg ) Func<double, double> Square = x => x * x; var result1 = Square(5); Console.WriteLine(result1); Func<double, double, double> Mul = (x, y) => x * y; var result2 = Mul(5,3); Console.WriteLine(result2); . פרמטרים ומחזיר ערך1-16 שמקבל ביןDelegate .מייצג פעולה עם ערך מוחזר -למבדה תוך שימוש ב Func Delegate Func<double[], double[], double> SumArray= (x, y) => { var dim = Math.Min(x.Length, y.Length); -למבדה תוך שימוש ב var sum = 0.0; Func Delegate x.ToList().ForEach(num => sum += num); y.ToList().ForEach(num => sum += num); return sum; }; double[] arr1 = new double[] { 1.1, 2.2, 3.3, 4.4 }; double[] arr2 = new double[] { 1.1, 2.2, 3.3 }; var result3 = SumArray(arr1, arr2); LambdaExpressionSample08 :דוגמת קוד Lambda Expression Func Delegate List<T>.Average<TSource> Method (IEnumerable<TSource>, Func<TSource, Decimal>) static void Main(string[] args) { int[] arr = { 100,200,300,400,500 }; double average = arr.Average(num => num); Console.WriteLine("The average is {0}.", average); } static void Main(string[] args) { int[] arr = { 100,200,300,400,500 }; double average = arr.Average(num => num + 100); Console.WriteLine("The average is {0}.", average); } static void Main(string[] args) { string[] fruits = { "Elimelech", "Zrubavel", "Havakuk", "Yerachmiel" }; double average = fruits.Average(s => s.Length); Console.WriteLine("The average string length is {0}.", average); } LambdaExpressionSample09 :דוגמת קוד Lambda Expression List -ביטויי למבדה ב . מכילה מספר פונקציות המתבססות על ביטויי למבדהList : הבאList -בדוגמאות הבאות נתבסס על ה List<String> names = new List<String>() { "Elimelech", "Zelda", "Zrubavel", "Havakuk", "Yerachmiel", "Yona", "Zalman", "Pirhiya", "Fruma" }; var tmp1 = names.OrderBy(str => str).ToList(); tmp1.ForEach(str => Console.WriteLine(str)); LambdaExpressionSample10 :דוגמת קוד :מיון Lambda Expression :מיון בסדר יורד var tmp2 = names.OrderByDescending(str => str).ToList(); tmp2.ForEach(str => Console.WriteLine(str)); var tmp3 = names.Where(str => str.Length > 6).ToList(); tmp3.ForEach(str => Console.WriteLine(str)); LambdaExpressionSample10 :דוגמת קוד :סינון Lambda Expression :מיון ע"פ קריטריון names.Sort((str1, str2) => str1.Length.CompareTo(str2.Length)); names.ForEach(str => Console.WriteLine(str)); :קיבוץ var tmp6 = names.GroupBy(str => str.Length).ToList(); tmp6.ForEach(arr => { Console.WriteLine(arr.Count()); arr.ToList().ForEach(str => Console.WriteLine(str)); }); Lambda Expression : הבאList -בדוגמאות הבאות נתבסס על ה List<Dog> dogs = new List<Dog>() { new Dog { Name = "Shuka", Age = 14 }, new Dog { Name = "Lucy", Age = 2 }, new Dog { Name = "Atraf", Age = 13 }, new Dog { Name = "Sig", Age = 8 }, }; :בחירת שדה var names1 = dogs.Select(x => x.Name).ToList(); names1.ForEach(str => Console.WriteLine(str)); dogs.Where(dog=>dog.Age%2==0). OrderBy(x => x.Name).ToList(). ForEach(dog => Console.WriteLine(dog.Name)); LambdaExpressionSample10 :דוגמת קוד :1 שרשור ביטויים Lambda Expression dogs.Where(dog => dog.Age > 5). OrderBy(dog => dog.Age).ToList(). ForEach(dog => Console.WriteLine(dog.Name)); LambdaExpressionSample10 :דוגמת קוד :2 שרשור ביטויים Lambda Expression :למבדה ואירועים public MainWindow() { InitializeComponent(); btn.Click += (sender, e) => lbl.Content = txt.Text; } LambdaExpressionWithWPF :דוגמת קוד Lambda Expression // Sample 01 Func<int, int> Square = (int x) => x * x; var result1 = Square(10); Console.WriteLine("Sample 01 - " + result1); :שעשועי למבדה // Sample 02 Func<int, int, int, int> Mul = (int num1, int num2, int num3) => num1 * num2 * num3; var result2 = Mul(2, 3, 4); Console.WriteLine("Sample 02 - " + result2); // Sample 03 Func<int[], int> Biggest = (int[] arr) => { int biggest = int.MinValue; arr.ToList().ForEach(num => biggest = (num > biggest) ? num : biggest); return biggest; }; int[] arr1 = new int[] { 1, 43, 66, 2, 88, 34, 51, 78, 99, -1, 77, 62 }; var result3 = Biggest(arr1); Console.WriteLine("Sample 03 - " + result3); Lambda Expression //Sample 04 Func<string, int> SquareStringLength = (string s) => s.Length * s.Length; var result4 = SquareStringLength("Abra Kadabra"); Console.WriteLine("Sample 04 - " + result4); // Sample 05 Predicate<string> ErrorStr = (string s) => { if (s.Length == 0) return true; else return false; }; Func<string, string, string> WhoIsLonger = (string str1, string str2) => { if (ErrorStr(str1) || ErrorStr(str2)) return "Error"; if (str1.Length == str2.Length) return "String are same length"; if (str1.Length > str2.Length) return str1; else return str2; }; var result5 = WhoIsLonger("Nissim Veniflaot", "Abra Kadabra"); Console.WriteLine("Sample 05 - " + result5); :שעשועי למבדה Lambda Expression שעשועי למבדה -פתרונות דוגמת קודLambdaEX : את הסילבוס ,חומרים ,מצגות ניתן להוריד ב: www.corner.co.il