Lambda表達式的本質是匿名函數,lambda表達式
1.委托的簡介:
委托可以簡單的理解為方法的列表,添加的方法的參數類型,個數,順序必須和委托一致,
也就是說委托起到了托管方法的作用,並且約束了要調用的方法.
1 //1聲明委托
2 public delegate void NoReturnNoPara();
3 public delegate void NoReturnWithPara(string name, int id);
4 public delegate int WithReturnNoPara();
5 public delegate string WithReturnWithPara(string name);
基礎代碼:

![]()
1 private void ShowPerson(string name, int id)
2 {
3 Console.WriteLine("this is id={0} name={1}", id, name);
4 }
ShowPerson

![]()
1 public class Student
2 {
3 public int Id { get; set; }
4 public int ClassId { get; set; }
5 public string Name { get; set; }
6 public int Age { get; set; }
7
8 public void Study()
9 {
10 Console.WriteLine("正在學習高級班");
11 }
12 }
13
14 /// <summary>
15 /// 班級
16 /// </summary>
17 public class Class
18 {
19 public int Id { get; set; }
20 public string Name { get; set; }
21 }
Student

![]()
1 {
2 Student student = new Student()
3 {
4 Id = 1,
5 ClassId = 11,
6 Name = "Courage-dhj"
7 };
8 student.Study();
9
10 var people = new //匿名類
11 {
12 Id = 1,
13 ClassId = 11,
14 Name = "Courage-dhj"
15 };
16 Console.WriteLine("{0} {1} {2}", people.Id, people.Name, people.ClassId);
17 }
匿名類
1 {
2 NoReturnWithPara method = new NoReturnWithPara(ShowPerson);//2 實例化委托
3 method.Invoke("盜墓者", 468);//3 委托調用
4 ShowPerson("盜墓者", 468);//方法的普通調用
5 }
2.匿名方法: 用delegate代替了方法名而已(修飾符和返回類型這裡看作方法名)
1 {
2 NoReturnWithPara method = new NoReturnWithPara(
3 delegate(string name, int id)
4 {
5 Console.WriteLine("this is id={0} name={1}", id, name);
6 });//匿名方法
7 method.Invoke("盜墓者", 468);
8 }
3.Lambda表達式
1 {
2 NoReturnWithPara method = new NoReturnWithPara(
3 (string name, int id) =>
4 {
5 Console.WriteLine("this is id={0} name={1}", id, name);
6 });//lambda表達式 把delegate換成箭頭
7 method.Invoke("盜墓者", 468);
8 //lambda表達式的本質就是一個匿名方法,,也就是一個方法
9 }
因為委托對方法有約束作用,所以,方法的參數類型可以省略
1 {
2 NoReturnWithPara method = new NoReturnWithPara(
3 (name, id) =>//lambda表達式方法主體只有一行,可以去掉大括號和分號
4 Console.WriteLine("this is id={0} name={1}", id, name)
5 );
6 method.Invoke("盜墓者", 468);
7 }
其他的形式:
1 {
2 NoReturnWithPara method = new NoReturnWithPara(
3 (name, id) =>//lambda表達式方法主體只有一行,可以去掉大括號和分號
4 Console.WriteLine("this is id={0} name={1}", id, name)
5 );
6 method.Invoke("盜墓者", 468);
7 }
{
//new一個委托的時候,可以簡寫
NoReturnWithPara method = (name, id) => Console.WriteLine("this is id={0} name={1}", id, name);//常用的形式
method.Invoke("盜墓者", 468);
}
4. Action 和 Func----這是系統自帶的委托,方便我們使用.
4.1-Action-無返回值的委托---看下面的in也看的出來啦!
先查看系統代碼的說明:

![]()
1 namespace System
2 {
3 // 摘要:
4 // 封裝一個方法,該方法不具有參數並且不返回值。
5 [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
6 public delegate void Action();
7 }
Action(一個參數)

![]()
1 namespace System
2 {
3 // 摘要:
4 // 封裝一個方法,該方法只有一個參數並且不返回值。
5 //
6 // 參數:
7 // obj:
8 // 此委托封裝的方法的參數。
9 //
10 // 類型參數:
11 // T:
12 // 此委托封裝的方法的參數類型。
13 public delegate void Action<in T>(T obj);
14 }
Action(in T)

![]()
1 1 namespace System
2 2 {
3 3 // 摘要:
4 4 // 封裝一個方法,該方法具有 16 個參數並且不返回值。
5 5 //
6 6 // 參數:
7 7 // arg1:
8 8 // 此委托封裝的方法的第一個參數。
9 9 //
10 10 // arg2:
11 11 // 此委托封裝的方法的第二個參數。
12 12 //
13 13 // arg3:
14 14 // 此委托封裝的方法的第三個參數。
15 15 //
16 16 // arg4:
17 17 // 此委托封裝的方法的第四個參數。
18 18 //
19 19 // arg5:
20 20 // 此委托封裝的方法的第五個參數。
21 21 //
22 22 // arg6:
23 23 // 此委托封裝的方法的第六個參數。
24 24 //
25 25 // arg7:
26 26 // 此委托封裝的方法的第七個參數。
27 27 //
28 28 // arg8:
29 29 // 此委托封裝的方法的第八個參數。
30 30 //
31 31 // arg9:
32 32 // 此委托封裝的方法的第九個參數。
33 33 //
34 34 // arg10:
35 35 // 此委托封裝的方法的第十個參數。
36 36 //
37 37 // arg11:
38 38 // 此委托封裝的方法的第十一個參數。
39 39 //
40 40 // arg12:
41 41 // 此委托封裝的方法的第十二個參數。
42 42 //
43 43 // arg13:
44 44 // 此委托封裝的方法的第十三個參數。
45 45 //
46 46 // arg14:
47 47 // 此委托封裝的方法的第十四個參數。
48 48 //
49 49 // arg15:
50 50 // 此委托封裝的方法的第十五個參數。
51 51 //
52 52 // arg16:
53 53 // 此委托封裝的方法的第十六個參數。
54 54 //
55 55 // 類型參數:
56 56 // T1:
57 57 // 此委托封裝的方法的第一個參數類型。
58 58 //
59 59 // T2:
60 60 // 此委托封裝的方法的第二個參數類型。
61 61 //
62 62 // T3:
63 63 // 此委托封裝的方法的第三個參數類型。
64 64 //
65 65 // T4:
66 66 // 此委托封裝的方法的第四個參數類型。
67 67 //
68 68 // T5:
69 69 // 此委托封裝的方法的第五個參數的類型。
70 70 //
71 71 // T6:
72 72 // 此委托封裝的方法的第六個參數的類型。
73 73 //
74 74 // T7:
75 75 // 此委托封裝的方法的第七個參數的類型。
76 76 //
77 77 // T8:
78 78 // 此委托封裝的方法的第八個參數的類型。
79 79 //
80 80 // T9:
81 81 // 此委托封裝的方法的第九個參數的類型。
82 82 //
83 83 // T10:
84 84 // 此委托封裝的方法的第十個參數的類型。
85 85 //
86 86 // T11:
87 87 // 此委托封裝的方法的第十一個參數的類型。
88 88 //
89 89 // T12:
90 90 // 此委托封裝的方法的第十二個參數的類型。
91 91 //
92 92 // T13:
93 93 // 此委托封裝的方法的第十三個參數的類型。
94 94 //
95 95 // T14:
96 96 // 此委托封裝的方法的第十四個參數的類型。
97 97 //
98 98 // T15:
99 99 // 此委托封裝的方法的第十五個參數的類型。
100 100 //
101 101 // T16:
102 102 // 此委托封裝的方法的第十六個參數的類型。
103 103 public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);
104 104 }
系統封裝-最多16個參數
實例化:
1 //接受0到16個參數的 無返回值 泛型委托
2 Action act1 = () => Console.WriteLine("123"); //1
3 Action<string> act2 = t => { };//2
4 Action<Student, Class, int, long, Student, Class, int, long, Student, Class, int, long, Student, Class, int, long> act3 = null;//3
4.2. Func---有返回值---看out就看得出來啦!

![]()
1 namespace System
2 {
3 // 摘要:
4 // 封裝一個不具有參數但卻返回 TResult 參數指定的類型值的方法。
5 //
6 // 類型參數:
7 // TResult:
8 // 此委托封裝的方法的返回值類型。
9 //
10 // 返回結果:
11 // 此委托封裝的方法的返回值。
12 [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
13 public delegate TResult Func<out TResult>();
14 }
無參數,有一個返回值

![]()
1 namespace System
2 {
3 // 摘要:
4 // 封裝一個具有一個參數並返回 TResult 參數指定的類型值的方法。
5 //
6 // 參數:
7 // arg:
8 // 此委托封裝的方法的參數。
9 //
10 // 類型參數:
11 // T:
12 // 此委托封裝的方法的參數類型。
13 //
14 // TResult:
15 // 此委托封裝的方法的返回值類型。
16 //
17 // 返回結果:
18 // 此委托封裝的方法的返回值。
19 [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
20 public delegate TResult Func<in T, out TResult>(T arg);
21 }
一個in,一個out

![]()
1 namespace System
2 {
3 // 摘要:
4 // 封裝一個方法,該方法具有 16 個參數,並返回 TResult 參數所指定的類型的值。
5 //
6 // 參數:
7 // arg1:
8 // 此委托封裝的方法的第一個參數。
9 //
10 // arg2:
11 // 此委托封裝的方法的第二個參數。
12 //
13 // arg3:
14 // 此委托封裝的方法的第三個參數。
15 //
16 // arg4:
17 // 此委托封裝的方法的第四個參數。
18 //
19 // arg5:
20 // 此委托封裝的方法的第五個參數。
21 //
22 // arg6:
23 // 此委托封裝的方法的第六個參數。
24 //
25 // arg7:
26 // 此委托封裝的方法的第七個參數。
27 //
28 // arg8:
29 // 此委托封裝的方法的第八個參數。
30 //
31 // arg9:
32 // 此委托封裝的方法的第九個參數。
33 //
34 // arg10:
35 // 此委托封裝的方法的第十個參數。
36 //
37 // arg11:
38 // 此委托封裝的方法的第十一個參數。
39 //
40 // arg12:
41 // 此委托封裝的方法的第十二個參數。
42 //
43 // arg13:
44 // 此委托封裝的方法的第十三個參數。
45 //
46 // arg14:
47 // 此委托封裝的方法的第十四個參數。
48 //
49 // arg15:
50 // 此委托封裝的方法的第十五個參數。
51 //
52 // arg16:
53 // 此委托封裝的方法的第十六個參數。
54 //
55 // 類型參數:
56 // T1:
57 // 此委托封裝的方法的第一個參數類型。
58 //
59 // T2:
60 // 此委托封裝的方法的第二個參數類型。
61 //
62 // T3:
63 // 此委托封裝的方法的第三個參數類型。
64 //
65 // T4:
66 // 此委托封裝的方法的第四個參數類型。
67 //
68 // T5:
69 // 此委托封裝的方法的第五個參數的類型。
70 //
71 // T6:
72 // 此委托封裝的方法的第六個參數的類型。
73 //
74 // T7:
75 // 此委托封裝的方法的第七個參數的類型。
76 //
77 // T8:
78 // 此委托封裝的方法的第八個參數的類型。
79 //
80 // T9:
81 // 此委托封裝的方法的第九個參數的類型。
82 //
83 // T10:
84 // 此委托封裝的方法的第十個參數的類型。
85 //
86 // T11:
87 // 此委托封裝的方法的第十一個參數的類型。
88 //
89 // T12:
90 // 此委托封裝的方法的第十二個參數的類型。
91 //
92 // T13:
93 // 此委托封裝的方法的第十三個參數的類型。
94 //
95 // T14:
96 // 此委托封裝的方法的第十四個參數的類型。
97 //
98 // T15:
99 // 此委托封裝的方法的第十五個參數的類型。
100 //
101 // T16:
102 // 此委托封裝的方法的第十六個參數的類型。
103 //
104 // TResult:
105 // 此委托封裝的方法的返回值類型。
106 //
107 // 返回結果:
108 // 此委托封裝的方法的返回值。
109 public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);
110 }
系統最多16個in參數
不過,不管怎麼變,Func的最後一個始終都時out,因為它時有返回值的呗!

![]()
1 //注意:這是一個新的類型,類型的不同包括了參數的個數的哦.
2 public delegate TResult ;
3 Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, in T17, out TResult>
4 (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9,
5 T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17);
如果16個參數不夠的話
1 //接受0到16個參數的 帶返回值 泛型委托
2 Func<int> func1 = () => DateTime.Now.Millisecond;//4--返回int類型
//下面都返回string類型
3 Func<int,
string> func2 = t => DateTime.Now.Millisecond.ToString();//5
4 Func<Student, Class, int, long, Student, Class, int, long, Student, Class, int, long, Student, Class, int, long,
string> func3 = null;//6
5 //調用自己寫的,17個參數
6 Func<Student, Student, Class, int, long, Student, Class, int, long, Student, Class, int, long, Student, Class, int, long,
string> func4 = null;//6
5 擴展方法: 靜態類的靜態方法第一個參數加上 this.(靜態類不一定要加上static,只要有靜態方法的類就是靜態類)
1 /// <summary>
2 /// 靜態類的靜態方法,第一個參數前面加上this
3 /// </summary>
4 public static class ExtendTest
5 {
6 /// <summary>
7 /// 轉成int 失敗給0寫日志
8 /// </summary>
9 /// <param name="sNumber"></param>
10 /// <returns></returns>
11 public static int ToInt(this string sNumber)
12 {
13 int iNumber = 0;
14 if (int.TryParse(sNumber, out iNumber))
15 {
16 return iNumber;
17 }
18 else
19 {
20 Console.WriteLine("{0} 轉換失敗,給出默認值", sNumber);
21 return 0;
22 }
23 }
24
25 public static void Study(this Student student)
26 {
27 Console.WriteLine("1234");
28 }
29
30 public static void StudyVip(this Student student)
31 {
32 Console.WriteLine("1234");
33 }
34
35 public static void ConsoleShow(this object oValue)
36 {
37 Console.WriteLine(oValue);
38 }
39
40 }
調用: 就像給某個類添加了一個方法一樣,所以才叫擴展方法啊!
1 string sNumber = "123345";
2 ExtendTest.ToInt(sNumber);//普通調用--返回一個int
3 sNumber.ToInt();//擴展方法調用--返回一個int
4
5 Student student = new Student()
6 {
7 Name = "天道無情(387-天道無情-男)"
8 };
9 student.StudyVip();
10 student.Study();
11 student.ConsoleShow();
不過,擴展方法並非給this 修飾的類添加了一個方法,而是通過this添加了一個紐帶.
當我們調用擴展方法時,還是進入了我們自己寫的方法裡.
只不過它看起來像時我們給一個類注入了一個方法而已.(這裡用注入很形象的形容)
記住:擴展方法時寫在一個外部的靜態類裡,並且是一個靜態方法,參數類型前加this.
6. Linq 查詢

![]()
1 private static List<Student> GetStudentList()
2 {
3 #region 初始化數據
4 List<Student> studentList = new List<Student>()
5 {
6 new Student()
7 {
8 Id=1,
9 Name="Answer(學委-answer-男)",
10 Age=25,
11 ClassId=2
12 },
13 new Student()
14 {
15 Id=2,
16 Name=" LTS_信仰I(196-LTS_信仰I-男-深圳)",
17 Age=36,
18 ClassId=1
19 },
20 new Student()
21 {
22 Id=3,
23 Name="ObjectIsNotFound",
24 Age=24,
25 ClassId=2
26 },
27 new Student()
28 {
29 Id=4,
30 Name="落單的候鳥",
31 Age=25,
32 ClassId=2
33 },
34 new Student()
35 {
36 Id=1,
37 Name="夜的樂章",
38 Age=31,
39 ClassId=2
40 },
41 new Student()
42 {
43 Id=1,
44 Name="知心dě朋友=(357-傑仔-男-廣州)",
45 Age=18,
46 ClassId=2
47 },
48 new Student()
49 {
50 Id=1,
51 Name="我",
52 Age=33,
53 ClassId=2
54 },
55 new Student()
56 {
57 Id=1,
58 Name="小逸",
59 Age=28,
60 ClassId=2
61 },
62 new Student()
63 {
64 Id=1,
65 Name="季雨林",
66 Age=27,
67 ClassId=2
68 },
69 new Student()
70 {
71 Id=1,
72 Name="dean",
73 Age=34,
74 ClassId=2
75 },
76 new Student()
77 {
78 Id=1,
79 Name="yup_h",
80 Age=21,
81 ClassId=1
82 }
83 };
84 #endregion 初始化數據
85 return studentList;
86 }
Linq用到的數據
普通程序員一般會想的方法:
1 List<Student> studentList = GetStudentList();
2 {
3 List<Student> targetList = new List<Student>();
4 foreach (var item in studentList)
5 {
6 if (item.Age > 25)
7 {
8 targetList.Add(item);
9 }
10 }
11 }
Linq查詢和Lambda表達式查詢:

![]()
1 //
2 // 摘要:
3 // 基於謂詞篩選值序列。
4 //
5 // 參數:
6 // source:
7 // 要篩選的 System.Collections.Generic.IEnumerable<T>。
8 //
9 // predicate:
10 // 用於測試每個元素是否滿足條件的函數。
11 //
12 // 類型參數:
13 // TSource:
14 // source 中的元素的類型。
15 //
16 // 返回結果:
17 // 一個 System.Collections.Generic.IEnumerable<T>,包含輸入序列中滿足條件的元素。
18 //
19 // 異常:
20 // System.ArgumentNullException:
21 // source 或 predicate 為 null。
22 public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
Where
注:Where本身是一個擴展方法.
Lambda
1 {
2 Console.WriteLine("**************************");
3 var targetList = studentList.Where<Student>(t => t.Age > 25);//陳述式
4 foreach (var item in targetList)
5 {
6 Console.WriteLine(" {0} {1}", item.Age, item.Name);
7 }
8 Console.WriteLine("**************************");
9
Linq
1 Console.WriteLine("**************************");
2 var list = from s in studentList
3 where s.Age > 25
4 select s;
5 foreach (var item in list)
6 {
7 Console.WriteLine(" {0} {1}", item.Age, item.Name);
8 }
為了弄懂原理,請看下面:
7. Lambda查詢模擬器:
this IEnumerable<TSource> source 是數據源
Func<TSource, bool> predicate 是查找的方法,第一個參數是傳入參數in,後一個是返回類型-用於判斷.
1 public static class ElevenExtend
2 {
3 public static IEnumerable<TSource> ElevenWhere<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
4 {
5 if (source == null) throw new Exception("null");
6
7 List<TSource> tList = new List<TSource>();
8
9 foreach (var item in source)
10 {
11 if (predicate.Invoke(item)) //調用時會返回一個bool
12 tList.Add(item);
13 }
14 return tList;
15 }
16 }
1 private static bool CheckStudentAge(Student student)
2 {
3 return student.Age > 25;
4 }
調用:
1 Func<Student, bool> func = new Func<Student, bool>(CheckStudentAge); //t => t.Age > 25;
2 var targetListEleven = studentList.ElevenWhere<Student>(func);//陳述式
foreach (var item in targetListEleven)
{
Console.WriteLine(" {0} {1}", item.Age, item.Name);
}
8. 其他的查詢:
1 {
2 Console.WriteLine("**************************");
3 var targetList =
studentList.Where<Student>(t => t.Age > 25 || t.Name.Contains("信仰") || new int[] { 1, 2 }.Contains(t.ClassId));//陳述式
4 foreach (var item in targetList)
5 {
6 Console.WriteLine(" {0} {1}", item.Age, item.Name);
7 }
8 }

![]()
1 //
2 // 摘要:
3 // 將序列中的每個元素投影到新表中。
4 //
5 // 參數:
6 // source:
7 // 一個值序列,要對該序列調用轉換函數。
8 //
9 // selector:
10 // 應用於每個元素的轉換函數。
11 //
12 // 類型參數:
13 // TSource:
14 // source 中的元素的類型。
15 //
16 // TResult:
17 // selector 返回的值的類型。
18 //
19 // 返回結果:
20 // 一個 System.Collections.Generic.IEnumerable<T>,其元素為對 source 的每個元素調用轉換函數的結果。
21 //
22 // 異常:
23 // System.ArgumentNullException:
24 // source 或 selector 為 null。
25 public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector);
Select投影查詢
1 {
2 var list = studentList.Select(s => new
3 {
4 IdAge = string.Format("{0}_{1}", s.Id, s.Age),
5 Name = s.Name
6 });
7 Console.WriteLine("**************************");
8 foreach (var student in list)
9 {
10 Console.WriteLine("Name={0} Age={1}", student.Name, student.IdAge);
11 }
12 }
對應的linq
1 {
2 var list = from student in studentList
3 //where student.Age > 25
4 select new
5 {
6 IdAge = string.Format("{0}_{1}", student.Id, student.Age),
7 Name = student.Name
8 };//語法糖
9
10 Console.WriteLine("**************************");
11 foreach (var student in list)
12 {
13 Console.WriteLine("Name={0} Age={1}", student.Name, student.IdAge);
14 }
15 }
1 {
2 Console.WriteLine("**************************");
3 foreach (var student in studentList.Where<Student>(s => s.ClassId == 2 && s.Id < 4)
4 .Select<Student, Student>(s =>
//Skip是跳過 Take是獲取
new Student { Age = s.Age, Name = string.Format("{0}_{1}", s.Name, s.Id) })
5 .OrderBy<Student, int>(s => s.Id)
6 .OrderByDescending<Student, int>(s => s.Age)
7 .Skip<Student>(1)//跳過1個
8 .Take<Student>(5))//獲取5個
9 {
10 Console.WriteLine("Name={0} Age={1}", student.Name, student.Age);
11 }
12 }
注:linq查詢編譯後還是調用的Lambda表達式.