亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

查詢表達式與循環控制

系統 1652 0

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

??? 查詢表達式使得編程風格從”命令式”變得更加的”聲明式”。查詢表達式定義想要的結果以及要達到該結果需要執行的方法,而不是具體的如何實現。這里重點是查詢表達式,通過擴展方法,查詢表達式使得能夠比命令式循環構造更能夠清楚的表達意圖。

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

      
        
          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());

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

或者更為簡潔的:

      foo.ForAll(
      
        Console
      
      .WriteLine); 
    

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

      
        
          public static class 
        
      
      
        
          Extensions 
        
        {

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

    {

        
        
          foreach 
        
        (T item 
        
          in 
        
        sequence)

        {

            action(item);

        }

    }

}
      
    

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

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

很多操作需要嵌套的循環操作,假設需要產生一個從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);

      }

   }

}
      
    

或者改為查詢表達式:

      
        
          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);

}
      
    

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

      
        
          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);

}
      
    

?

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

      
        
          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);

}
      
    

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

?? 查詢表達式比循環控制結構更好的一點是:查詢表示式能夠更好的組合,他能夠將算法組織在一個很小的精簡的片段內來執行一系列的操作。查詢的惰性執行模型也使得開發者能夠在一個循環類執行一系列的操作。而查詢表達式則不能做到這一點。你必須存儲每一次循環的結果,然后構造新的循環操作來執行上一次的操作結果。

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

每一個查詢表達式有一個對應的方法調用是的表達式,有時候,查詢表達式更自然有時候方法調用是的表達式更自然。顯然在上面的例子中,查詢表達式版本更易讀,下面是方法調用的版本:

      
        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);

}
    

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

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

?? C#最開始是一種命令式編程語言,你能夠使用之前最熟悉的方法去編寫代碼。但是這些傳統的方法可能不是最好的。當你發現需要使用循環結構去執行某種操作的時候,試試能夠將它改寫為查詢表達式的方式,如果查詢表達式不起作用,試試方法表達式,在大多數情況下,你會發現使用查詢表達式或者方法表達式會比使用傳統的循環式的命令式結構能使得代碼變得更加簡潔和清晰。

查詢表達式與循環控制


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

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

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 牛牛影视在线观看片免费 | 2021久久精品永久免费 | 国产草 | 国产成人午夜性a一级毛片 国产成人午夜性视频影院 国产成人系列 | 中文字幕免费在线观看 | 天天干天天射天天操 | 欧美精品亚洲网站 | 成人在线免费视频播放 | 亚洲一区综合 | 日韩在线成人 | 久久中文字幕综合婷婷 | 欧美午夜在线视频 | 亚洲综合图片小说区热久久 | 久久精品国产只有精品2020 | 亚洲一区欧美 | 久久综合亚洲一区二区三区 | 欧美视频一区二区三区在线观看 | 99视频在线国产 | 欧美一级精品高清在线观看 | 国产精品久久久久影院 | 日韩精美视频 | 美女黄www视频 | 欧美一级视频免费观看 | 成人国产一区二区 | 99热热久久这里只有精品8 | 日操夜操天天操 | 亚洲视频网站在线观看 | 日韩高清毛片 | 欧美aaaa黄色一级毛片 | 国产日韩在线看 | 久久骚| 香蕉成人影院 | 国产亚洲精品精品国产亚洲综合 | 亚洲国产片 | 成人午夜精品久久久久久久小说 | 国产不卡精品一区二区三区 | 日本欧美一区二区三区在线 | 成人短视频在线免费观看 | 日本中文在线视频 | 成人毛片高清视频观看 | 亚洲国内|