黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

查詢表達(dá)式與循環(huán)控制

系統(tǒng) 2105 0

??? For,do… while,while ,foreach是大多數(shù)編程語言中常用的循環(huán)控制語句,在C#中查詢表達(dá)式也能實現(xiàn)同樣的效果。

??? 查詢表達(dá)式使得編程風(fēng)格從”命令式”變得更加的”聲明式”。查詢表達(dá)式定義想要的結(jié)果以及要達(dá)到該結(jié)果需要執(zhí)行的方法,而不是具體的如何實現(xiàn)。這里重點是查詢表達(dá)式,通過擴(kuò)展方法,查詢表達(dá)式使得能夠比命令式循環(huán)構(gòu)造更能夠清楚的表達(dá)意圖。

??? 下面的語句顯示了一個命令式風(fēng)格的填充一個數(shù)組并打印到控制臺上:

      
        
          int
        
        [] foo = 
        
          new int
        
        [100];


        
          for 
        
        (
        
          int 
        
        num = 0; num < foo.Length; num++)

{

   foo[num] = num * num;

}


        
          foreach 
        
        (
        
          int 
        
        i 
        
          in 
        
        foo)

{

   
        
          Console
        
        .WriteLine(i.ToString());

}  
      
    
即使實現(xiàn)這么一小點功能,依然注重的是如何實現(xiàn)而不是怎樣實現(xiàn),將這段代碼改為查詢表達(dá)式能夠使得代碼更易讀和使用:
      
        
          int
        
        [] foo = (
        
          from 
        
        n 
        
          in 
        
        
          Enumerable
        
        .Range(0, 100) 
        
          select 
        
        n * n).ToArray();
      
    
第二個循環(huán)可以利用擴(kuò)展方法改寫為:
      
        foo.ForAll(n => 
        
          Console
        
        .WriteLine(n));
      
    

或者更為簡潔的:

      foo.ForAll(
      
        Console
      
      .WriteLine); 
    

在.NET BCL中ForEach擴(kuò)展方法有針對List<T>的實現(xiàn)方法。我們可以添加一個針對IEnumerable<T>的ForAll擴(kuò)展方法實現(xiàn)如下:

      
        
          public static class 
        
      
      
        
          Extensions 
        
        {

    
        
          public static void 
        
        ForAll<T>(
        
          this 
        
        
          IEnumerable
        
        <T> sequence, 
        
          Action
        
        <T> action)

    {

        
        
          foreach 
        
        (T item 
        
          in 
        
        sequence)

        {

            action(item);

        }

    }

}
      
    

? 可能看起來不起眼,只不過是一個擴(kuò)展方法而已,但是這能夠使得代碼能夠更多的重用,任何時候要對一個序列元素執(zhí)行操作,F(xiàn)orAll就能夠派上用場。

??? 以上問題可能看上去比較簡單,不足以看出使用查詢語法所帶來的好處,下面來看個復(fù)雜一點的。

很多操作需要嵌套的循環(huán)操作,假設(shè)需要產(chǎn)生一個從0到99的(X,Y)對,通常的做法是:

      
        
          public static 
        
        
          IEnumerable
        
        <
        
          Tuple
        
        <
        
          Int32
        
        , 
        
          Int32
        
        >> ProduceIndices()

{

   
        
          for 
        
        (
        
          int 
        
        x = 0; x < 100; x++)

   {

      
        
          for 
        
        (
        
          int 
        
        y = 0; y < 100; y++)

      {

          
        
          yield return 
        
        
          Tuple
        
        .Create(x, y);

      }

   }

}
      
    

或者改為查詢表達(dá)式:

      
        
          public static 
        
        
          IEnumerable
        
        <
        
          Tuple
        
        <
        
          Int32
        
        , 
        
          Int32
        
        >> ProduceIndices()

{

    
        
          return from 
        
        x 
        
          in 
        
        
          Enumerable
        
        .Range(1, 100)

           
        
          from 
        
        y 
        
          in 
        
        
          Enumerable
        
        .Range(1, 100)

           
        
          select 
        
        
          Tuple
        
        .Create(x, y);

}
      
    

兩者看起來差不多,但是隨著問題的復(fù)雜,查詢表達(dá)式仍然能夠保持簡潔。現(xiàn)在將問題改為:只產(chǎn)生x和y相加小于100的點對,比較兩者的實現(xiàn):

      
        
          public static 
        
        
          IEnumerable
        
        <
        
          Tuple
        
        <
        
          Int32
        
        , 
        
          Int32
        
        >> ProduceIndices2()

{

    
        
          for 
        
        (
        
          int 
        
        x = 0; x < 100; x++)

    {

        
        
          for 
        
        (
        
          int 
        
        y = 0; y < 100; y++)

        {

            
        
          if 
        
        (x+y<100)

                
        
          yield return 
        
        
          Tuple
        
        .Create(x, y);

        }

    }

}




        
          public static 
        
        
          IEnumerable
        
        <
        
          Tuple
        
        <
        
          Int32
        
        , 
        
          Int32
        
        >> ProduceIndices2()

{

    
        
          return from 
        
        x 
        
          in 
        
        
          Enumerable
        
        .Range(1, 100)

           
        
          from 
        
        y 
        
          in 
        
        
          Enumerable
        
        .Range(1, 100)

           
        
          where 
        
        x+y<100

           
        
          select 
        
        
          Tuple
        
        .Create(x, y);

}
      
    

?

差距仍不明顯,但是命令式語句開始隱藏我們想要的意圖。再將問題變得復(fù)雜一些。現(xiàn)在,我們需要將返回的點按照距離原點位置的距離降序排列。

      
        
          public static 
        
        
          IEnumerable
        
        <
        
          Tuple
        
        <
        
          Int32
        
        , 
        
          Int32
        
        >> ProduceIndices3()

{

    
        
          var 
        
        storage = 
        
          new 
        
        
          List
        
        <
        
          Tuple
        
        <
        
          int
        
        , 
        
          int
        
        >>();

    
        
          for 
        
        (
        
          int 
        
        x = 0; x < 100; x++)

    {

        
        
          for 
        
        (
        
          int 
        
        y = 0; y < 100; y++)

        {

            
        
          if 
        
        (x+y<100)

            storage.Add(
        
          Tuple
        
        .Create(x, y));

        }

    }

    storage.Sort((point1,point2)=>

                (point2.Item1*point2.Item1+point2.Item2*point2.Item2).CompareTo

                (point1.Item1 * point1.Item1 + point1.Item2 * point1.Item2)

                );

    
        
          return 
        
        storage;

}




        
          public static 
        
        
          IEnumerable
        
        <
        
          Tuple
        
        <
        
          Int32
        
        , 
        
          Int32
        
        >> ProduceIndices3()

{

    
        
          return from 
        
        x 
        
          in 
        
        
          Enumerable
        
        .Range(1, 100)

           
        
          from 
        
        y 
        
          in 
        
        
          Enumerable
        
        .Range(1, 100)

           
        
          where 
        
        x + y < 100

           
        
          orderby 
        
        (x * x + y * y) 
      
      
        
          descending select 
        
        
          Tuple
        
        .Create(x, y);

}
      
    

?? 現(xiàn)在,差距開始出現(xiàn)了,命令式的風(fēng)格時的代碼難以理解,如果不認(rèn)真的看,很難一下子明白比較函數(shù)后面一堆東西返回的是什么。如果沒有注釋的話,這段命令式代碼比較難懂。命令式風(fēng)格的代碼過多的強調(diào)了代碼執(zhí)行的過程,很容易在這復(fù)雜的過程中迷失我們最初想要達(dá)到的目的。

?? 查詢表達(dá)式比循環(huán)控制結(jié)構(gòu)更好的一點是:查詢表示式能夠更好的組合,他能夠?qū)⑺惴ńM織在一個很小的精簡的片段內(nèi)來執(zhí)行一系列的操作。查詢的惰性執(zhí)行模型也使得開發(fā)者能夠在一個循環(huán)類執(zhí)行一系列的操作。而查詢表達(dá)式則不能做到這一點。你必須存儲每一次循環(huán)的結(jié)果,然后構(gòu)造新的循環(huán)操作來執(zhí)行上一次的操作結(jié)果。

?? 最后一個例子演示了如何工作。操作組合了過濾(where子句),排序(orderby 子句)以及投影(select語句),所有這些操作在一次遍歷操作中完成。而命令式版本的方法需要創(chuàng)建一個零時的存儲對象storage,然后對這個對象分別執(zhí)行一些列操作。

每一個查詢表達(dá)式有一個對應(yīng)的方法調(diào)用是的表達(dá)式,有時候,查詢表達(dá)式更自然有時候方法調(diào)用是的表達(dá)式更自然。顯然在上面的例子中,查詢表達(dá)式版本更易讀,下面是方法調(diào)用的版本:

      
        public static 
      
      
        IEnumerable
      
      <
      
        Tuple
      
      <
      
        Int32
      
      , 
      
        Int32
      
      >> ProduceIndices3()

{

    
      
        return 
      
      Enumerable.Range(1, 100).

            SelectMany(x => Enumerable.Range(1, 100),

            (x, y) => 
      
        Tuple
      
      .Create(x, y)).Where(pt => pt.Item1 + pt.Item2 < 100).

            OrderByDescending(pt => pt.Item1 * pt.Item1 + pt.Item2 * pt.Item2);

}
    

?? 在這個例子中,查詢表達(dá)式可能比方法表達(dá)式更易讀,但其他例子可能不同。有些方法表達(dá)式并沒有對應(yīng)的查詢表達(dá)式。一些方法,如Take,TakeWhile,Skip,SkipWhile,Min,以及Max在一些情況下需要使用方法表達(dá)式。

?? 有些人可能會人會查詢表達(dá)式在執(zhí)行速度上比循環(huán)執(zhí)慢,這一點要看具體的情況。有時候清晰的代碼可能比速度更重要。在改進(jìn)程序算法之前,可以考慮LINQ的并行擴(kuò)展庫PLINQ,可以使用.AsParallel()來使的查詢操作能夠并行執(zhí)行。

?? C#最開始是一種命令式編程語言,你能夠使用之前最熟悉的方法去編寫代碼。但是這些傳統(tǒng)的方法可能不是最好的。當(dāng)你發(fā)現(xiàn)需要使用循環(huán)結(jié)構(gòu)去執(zhí)行某種操作的時候,試試能夠?qū)⑺膶憺椴樵儽磉_(dá)式的方式,如果查詢表達(dá)式不起作用,試試方法表達(dá)式,在大多數(shù)情況下,你會發(fā)現(xiàn)使用查詢表達(dá)式或者方法表達(dá)式會比使用傳統(tǒng)的循環(huán)式的命令式結(jié)構(gòu)能使得代碼變得更加簡潔和清晰。

查詢表達(dá)式與循環(huán)控制


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論