lambda演變歷史 .NetFramework1.0 1.1下,lambda表達式是這樣去寫的,首先聲明一個無參無返回值delegate委托,再聲明一個無參無返回值的方法,把這個方法當做參數一樣傳遞給委托 你也可以聲明一個有參數和有返回值的委托,就像聲明方法一樣: .NetFramework2.0 ...
lambda演變歷史
.NetFramework1.0 1.1下,lambda表達式是這樣去寫的,首先聲明一個無參無返回值delegate委托,再聲明一個無參無返回值的方法,把這個方法當做參數一樣傳遞給委托
public delegate void NoReturnNoPara(); NoReturnNoPara method = new NoReturnNoPara(this.DoNothing); private void DoNothing() { Console.WriteLine("This is DoNothing"); }
你也可以聲明一個有參數和有返回值的委托,就像聲明方法一樣:
public delegate void NoReturnWithPara(int x, string y);//1 聲明委托 NoReturnWithPara method = new NoReturnWithPara(this.Study); private void Study(int id, string name) { Console.WriteLine($"{id} {name} 學習.Net高級班"); } //method.Invoke(123, "strPram"); method(123,"strParm");//這兩種調用方式是等效的
.NetFramework2.0 匿名方法,delegate關鍵字,可以訪問局部變數
NoReturnWithPara method = new NoReturnWithPara(delegate (int id, string name) { Console.WriteLine(i); }); method.Invoke(234, "bingle");
.NetFramework3.0 把delegate關鍵字去掉,增加了一個箭頭goes to,lambda表達式 參數列表=>方法體
NoReturnWithPara method = new NoReturnWithPara( (int id, string name) => { Console.WriteLine($"id:{id},name: {name}"); }); method.Invoke(123, "bingle");
省略參數類型,編譯器的語法糖,雖然沒寫,編譯時還是有的,根據委托推算
NoReturnWithPara method = new NoReturnWithPara( (id, name) => { Console.WriteLine($"id:{id}name: {name}"); }); method.Invoke(123, "bingle");
如果方法體只有一行,可以去掉大括弧和分號
NoReturnWithPara method = new NoReturnWithPara( (id, name) => Console.WriteLine($"id:{id},name: {name} ")); method.Invoke(123, "bingle");
new NoReturnWithPara可以省掉,也是語法糖,編譯器自動加上
NoReturnWithPara method = (id, name) => Console.WriteLine($"id:{id} ,name:{name}"); method.Invoke(123, "bingle");
lambda是什麼?
lambda只是實例化委托,是匿名方法,但是在編譯的時候會分配一個名字,還會產生一個私有sealed類,這裡增加一個剛發
lambda在多播委托
NoReturnWithPara method = new NoReturnWithPara(this.Study); method += this.Study; method += (id, name) => Console.WriteLine($"{id} {name}"); method -= this.Study; method -= (id, name) => Console.WriteLine($"{id} {name} "); //多播委托裡面的lambda無法移除, 不是2個實例,其實是2個不同的方法 method.Invoke(345, "bingle");
匿名方法或者lamdba表達式是不是只能是無返回值的?不是的,可以有返回值的。這裡面的Action和Func是內置的委托
Action action0 = () => { }; Action<string> action1 = s => Console.WriteLine(s); //參數只有一個 可以省略小括弧 Func<int> func0 = () => DateTime.Now.Month;//如果方法體只有一行,去掉大括弧分號return int iResult = func0.Invoke();
yield關鍵字:
含有yield的函數說明它是一個生成器,而不是普通的函數。當程式運行到yield這一行時,該函數會返回值,並保存當前域的所有變數狀態。
等到該函數下一次被調用時,會從上一次中斷的地方開始執行,一直遇到下一個yield,程式返回值,併在此保存當前狀態;如此反覆,知道函數正常執行完成。
迭代器模式是設計模式中行為模式的一個例子,他是一種簡化對象間通訊的模式,也是一種非常容易理解和使用的模式。
簡單來說,迭代器模式使得你能夠獲取到序列中的所有元素,而不用關心器類型是array,list,linked或者其他的什麼序列結構。
這一點使得能夠非常搞笑的構建數據處理通道(data pipeline),即數據能夠進入處理通道,進行一系列的變換,活著過濾,然後得到結果。事實上,這正是Linq的核心模式。
在.NET中,迭代器模式被IEnumerator和IEnumerable及其對應的泛型介面所封裝。如果一個類實現了IEnumerable介面,那麼就能夠被迭代。
調用GetEnumerator方法將返回IEnumerator介面的實現,它就是迭代器本身。迭代器類似資料庫中的游標,它是數據序列中的一個位置記錄。
迭代器只能向前移動,同一個數據序列中跨域有多個迭代器同時對數據進行操作。
一個普通的獲取數據的方法:
public IEnumerable<int> CommonMethod() { List<int> results = new List<int>(); int counter = 0; int result = 1; while (counter++ < 10) { Thread.Sleep(1000); Console.WriteLine($"獲取{counter}次數據"); result = result * 2; results.Add(result); } return results; }
yield獲取數據:
public IEnumerable<int> YieldMethod() { int counter = 0; int result = 1; while (counter++ < 10) { Thread.Sleep(1000); Console.WriteLine($"獲取{counter}次數據"); result = result * 2; yield return result; } }
這兩個方法,可以通過調試看到他們之間的區別
這是普通方法獲取數據的調試結果:
這是yield方法調試獲得的結果:
public IEnumerable<int> CreateEnumerable() { try { Console.WriteLine("{0} CreateEnumerable()方法開始", DateTime.Now); for (int i = 0; i < 5; i++) { Console.WriteLine("{0}開始 yield {1}", DateTime.Now, i); yield return i; Console.WriteLine("{0}yield 結束", DateTime.Now); if (i == 4) { yield break;//直接終結迭代 4會出現的,, } } Console.WriteLine("{0} Yielding最後一個值", DateTime.Now); yield return -1; Console.WriteLine("{0} CreateEnumerable()方法結束", DateTime.Now); } finally { Console.WriteLine("停止迭代!"); } } IEnumerable<int> iterable = new Test().CreateEnumerable();//1 不會直接執行 IEnumerator<int> iterator = iterable.GetEnumerator(); Console.WriteLine("開始迭代"); while (true) { Console.WriteLine("調用MoveNext方法……"); Boolean result = iterator.MoveNext();//2 正式開啟CreateEnumerable Console.WriteLine("MoveNext方法返回的{0}", result); if (!result) { break; } Console.WriteLine("獲取當前值……"); Console.WriteLine("獲取到的當前值為{0}", iterator.Current); }
這是調試獲得的結果: