<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      先說IEnumerable,我們每天用的foreach你真的懂它嗎?

      我們先思考幾個(gè)問題:

      1. 為什么在foreach中不能修改item的值?
      2. 要實(shí)現(xiàn)foreach需要滿足什么條件?
      3. 為什么Linq to Object中要返回IEnumerable?

      接下來,先開始我們的正文。

      自己實(shí)現(xiàn)迭代器

      .net中迭代器是通過IEnumerable和IEnumerator接口來實(shí)現(xiàn)的,今天我們也來依葫蘆畫瓢。

      首先來看看這兩個(gè)接口的定義:

      并沒有想象的那么復(fù)雜。其中IEnumerable只有一個(gè)返回IEnumerator的GetEnumerator方法。而IEnumerator中有兩個(gè)方法加一個(gè)屬性。

      接下來開發(fā)畫瓢,我們繼承IEnumerable接口并實(shí)現(xiàn):

      下面使用原始的方式調(diào)用:

      有朋友開始說了,我們平時(shí)都是通過foreache來取值的,沒有這樣使用過啊。好吧,我們來使用foreach循環(huán):

      為什么說基本上是等效的呢?我們先看打印結(jié)果,在看反編譯代碼。

      由此可見,兩者有這么個(gè)關(guān)系:

      我們可以回答第一個(gè)問題了“為什么在foreach中不能修改item的值?”:

      我們還記得IEnumerator的定義嗎

       

      接口的定義就只有g(shù)et沒有set。所以我們在foreach中不能修改item的值。

      我們再來回答第二個(gè)問題:“要實(shí)現(xiàn)foreach需要滿足什么條件?”:

      必須實(shí)現(xiàn)IEnumerable接口?NO

      我們自己寫的MyIEnumerable刪掉后面的IEnumerable接口一樣可以foreach(不信?自己去測試)。

      所以要可以foreach只需要對象定義了GetEnumerator無參方法,并且返回值是IEnumerator或其對應(yīng)的泛型。細(xì)看下圖:

      也就是說,只要可以滿足這三步調(diào)用即可。不一定要繼承于IEnumerable。有意思吧!下次面試官問你的時(shí)候一定要爭個(gè)死去活來啊,哈哈!

      yield的使用

      你肯定發(fā)現(xiàn)了我們自己去實(shí)現(xiàn)IEnumerator接口還是有些許麻煩,并且上面的代碼肯定是不夠健壯。對的,.net給我們提供了更好的方式。

      你會(huì)發(fā)現(xiàn)我們連MyIEnumerator都沒要了,也可以正常運(yùn)行。太神奇了。yield到底為我們做了什么呢?

      好家伙,我們之前寫的那一大坨。你一個(gè)yield關(guān)鍵字就搞定了。最妙的是這塊代碼:

      這就是所謂的狀態(tài)機(jī)吧!

      我們繼續(xù)來看GetEnumerator的定義和調(diào)用:

      我們調(diào)用GetEnumerator的時(shí)候,看似里面for循環(huán)了一次,其實(shí)這個(gè)時(shí)候沒有做任何操作。只有調(diào)用MoveNext的時(shí)候才會(huì)對應(yīng)調(diào)用for循環(huán):

      現(xiàn)在我想可以回答你“為什么Linq to Object中要返回IEnumerable?”:

      因?yàn)镮Enumerable是延遲加載的,每次訪問的時(shí)候才取值。也就是我們在Lambda里面寫的where、select并沒有循環(huán)遍歷(只是在組裝條件),只有在ToList或foreache的時(shí)候才真正去集合取值了。這樣大大提高了性能。

      如:

      這個(gè)時(shí)候得到了就是IEnumerable對象,但是沒有去任何遍歷的操作。(對照上面的gif動(dòng)圖看

      什么,你還是不信?那我們再來做個(gè)實(shí)驗(yàn),自己實(shí)現(xiàn)MyWhere:

      現(xiàn)在看到了吧。執(zhí)行到MyWhere的時(shí)候什么動(dòng)作都沒有(返回的就是IEnumerable),只有執(zhí)行到ToList的時(shí)候才代碼才真正的去遍歷篩選。

      這里的MyWhere其實(shí)可以用擴(kuò)展方法來實(shí)現(xiàn),提升逼格。(Linq的那些查詢操作符就是以擴(kuò)展的形式實(shí)現(xiàn)的)[了解擴(kuò)展方法]。

      怎樣高性能的隨機(jī)取IEnumerable中的值

      這段代碼來源《深入理解C#》,個(gè)人覺得非常妙。貼出來給大家欣賞哈。

       

      結(jié)束:

      demo下載:http://pan.baidu.com/s/1dE94c1b

      接下篇:《再講IQueryable<T>,揭開表達(dá)式樹的神秘面紗

       

      本文以同步至《C#基礎(chǔ)知識鞏固系列

      posted @ 2016-08-15 08:56  農(nóng)碼一生  閱讀(29238)  評論(60)    收藏  舉報(bào)
      .
      主站蜘蛛池模板: 少妇人妻偷人精品一区二| 国产精品无码无需播放器| 永久免费在线观看蜜桃视频| 日本一区二区三区免费播放视频站| 人妻少妇88久久中文字幕| 精品无人区卡一卡二卡三乱码| 久久精品日韩av无码| 中文字幕无码av激情不卡| 国产精品小仙女自拍视频| 亚洲国产长腿丝袜av天堂 | 国产欧美日韩精品a在线观看| 国产精品一区二区麻豆蜜桃| 亚洲午夜爱爱香蕉片| 东京热人妻无码一区二区av| 国产日韩综合av在线| 国产又色又刺激高潮视频| 动漫精品中文无码卡通动漫 | 欧美亚洲综合久久偷偷人人| 啪啪av一区二区三区| 亚洲国产综合精品2020| av鲁丝一区鲁丝二区鲁丝三区| 亚洲黄色第一页在线观看| 野花韩国高清电影| 永久免费AV无码国产网站| 国内精品卡一卡二卡三| 久久99九九精品久久久久蜜桃 | 久久综合久中文字幕青草| 国产精品久久久久影院亚瑟| 性色av无码不卡中文字幕| 青青草无码免费一二三区| 国产精品视频白浆免费视频| 国99久9在线 | 免费| 亚洲午夜无码久久久久蜜臀av| 亚洲精品成人久久av| 免费高潮了好湿h视频| 亚洲a人片在线观看网址| 欧美成人精品手机在线| 亚洲狠狠爱一区二区三区| 亚洲综合精品第一页| 亚洲精品第一区二区三区| 久久精品麻豆日日躁夜夜躁|