中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解.NET 3.5擴展方法和Lambda表達式

發布時間:2021-11-25 09:11:15 來源:億速云 閱讀:125 作者:柒染 欄目:編程語言

如何理解.NET 3.5擴展方法和Lambda表達式,相信很多沒有經驗的人對此束手無策,為此本文總結了問題出現的原因和解決方法,通過這篇文章希望你能解決這個問題。

對于上文的簡化需求,使用Lambda表達式和內置的.NET 3.5擴展方法便可以寫成這樣:

static List< int> EvenSquareLambda(IEnumerable< int> source)  {      return source.Where(i => i % 2 == 0).Select(i => i * i).ToList();  }

.NET 3.5擴展方法的延遲效果

應該已經有許多朋友了解了.NET 3.5中處理集合時擴展方法具有“延遲”的效果,也就是說Where和Select中的委托(兩個Lambda表達式)只有在調用ToList方法的時候才會執行。這是優點也是陷阱,在使用這些方法的時候我們還是需要了解這些方法的效果如何。不過這些方法其實都沒有任何任何“取巧”之處,換句話說,它們的行為和我們正常思維的結果是一致的。如果您想得明白,能夠自己寫出類似的方法,或者能夠“自圓其說”,十有八九也不會有什么偏差。但是如果您想不明白它們是如何構造的,還是通過實驗來確定一下吧。實驗的方式其實很簡單,只要像我們之前驗證“重復計算”陷阱那種方法就可以了,也就是觀察委托的執行時機和順序進行判斷。

好,回到我們現在的問題。我們知道了“延遲”效果,我們知道了Where和Select會在ToList的時候才會進行處理。不過,它們的處理方式是什么樣的,是像我們的“普通方法”那樣“創建臨時容器(如List< T>),并填充返回”嗎?對于這點我們不多作分析,還是通過“觀察委托執行的時機和順序”來尋找答案。使用這種方式的關鍵,便是在委托執行時打印出一些信息。為此,我們需要這樣一個Wrap方法(您自己做試驗時也可以使用這個方法):

static Func< T, TResult> Wrap< T, TResult>(      Func< T, TResult> func,      string messgaeFormat)  {      return i =>      {          var result = func(i);          Console.WriteLine(messgaeFormat, i, result);          return result;      };  }

Wrap方法的目的是將一個Func< T, TResult>委托對象進行封裝,并返回一個類型相同的委托對象。每次執行封裝后的委托時,都會執行我們提供的委托對象,并根據我們傳遞的messageFormat格式化輸出。例如:

var wrapper = Wrap< int, int>(i => i + 1, "{0} + 1 = {1}");  for (var i = 0; i <  3; i++) wrapper(i);

則會輸出:

0 + 1 = 1 1 + 1 = 2 2 + 1 = 3

那么,我們下面這段代碼會打印出什么內容呢?

List< int> source = new List< int>();  for (var i = 0; i <  10; i++) source.Add(i);   var finalSource = source      .Where(Wrap< int, bool>(i => i % 3 == 0, "{0} can be divided by 3? {1}"))      .Select(Wrap< int, int>(i => i * i, "The square of {0} equals {1}."))      .Where(Wrap< int, bool>(i => i % 2 == 0, "The result {0} can be devided by 2? {1}"));   Console.WriteLine("===== Start =====");  foreach (var item in finalSource)  {      Console.WriteLine("===== Print {0} =====", item);  }

我們準備一個列表,其中包含0到9共十個元素,并將其進行Where…Select…Where的處理,您可以猜出經過foreach之后屏幕上的內容嗎?

===== Start =====  0 can be divided by 3? True  The square of 0 equals 0.  The result 0 can be devided by 2? True  ===== Print 0 =====  1 can be divided by 3? False  2 can be divided by 3? False  3 can be divided by 3? True  The square of 3 equals 9.  The result 9 can be devided by 2? False  4 can be divided by 3? False  5 can be divided by 3? False  6 can be divided by 3? True  The square of 6 equals 36.  The result 36 can be devided by 2? True  ===== Print 36 =====  7 can be divided by 3? False  8 can be divided by 3? False  9 can be divided by 3? True  The square of 9 equals 81.  The result 81 can be devided by 2? False

列表中元素的執行順序是這樣的:
***個元素“0”經過Where…Select…Where,***被Print出來。
第二個元素“1”經過Where,中止。
第三個元素“2”經過Where,中止。
第四個元素“4”經過Where…Select…Where,中止。
……

.NET 3.5擴展方法的神奇之處

這說明了,我們使用.NET框架自帶的Where或Select方法,最終的效果和上一節中的“合并循環”類似。因為,如果創建了臨時容器保存元素的話,就會在***個Where中把所有元素都交由***個委托(i => i % 3 == 0)執行,然后再把過濾后的元素交給Select中的委托(i => i * i)執行。請注意,在這里“合并循環”的效果對外部是隱藏的,我們的代碼似乎還是一步一步地處理集合。換句話說,我們使用“分解循環”的清晰方式,但獲得了“合并循環”的高效實現。這就是.NET框架這些擴展方法的神奇之處1。

在我們進行具體的性能測試之前,我們再來想一下,這里出現了那么多IEnumerable對象實現了哪個GoF 23中的模式呢?枚舉器?看到IEnumerable就說枚舉器也太老生常談了。其實這里同樣用到了“裝飾器”模式。每次Where或Select之后其實都是使用了一個新的IEnumerable對象來封裝原有的對象,這樣我們遍歷新的枚舉器時便會獲得“裝飾”后的效果。因此,以后如果有人問您“.NET框架中有哪些的裝飾器模式的體現”,除了人人都知道的Stream之外,您還可以回答說“.NET 3.5中System.Linq.Enumerable類里的一些擴展方法”,多酷。

看完上述內容,你們掌握如何理解.NET 3.5擴展方法和Lambda表達式的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

黄石市| 毕节市| 武清区| 香格里拉县| 繁昌县| 自治县| 大城县| 宁河县| 壤塘县| 上高县| 阳高县| 西宁市| 北海市| 淳安县| 宜宾县| 大竹县| 故城县| 樟树市| 阆中市| 邢台县| 新干县| 彝良县| 拉萨市| 称多县| 离岛区| 客服| 靖宇县| 临清市| 涪陵区| 衡阳县| 诸城市| 武安市| 喜德县| 左权县| 昌乐县| 逊克县| 清流县| 抚宁县| 枝江市| 措美县| 广饶县|