2016-11-28 17 views
3

素朴なヒントとして、IEnumerable.Any()を使用することがよくあります。なぜなら、列挙型全体を必ずしもトラバースする必要がないからです。コンパイラはIEnumerable <T> .Count()との比較を最適化しますか?

Enumerableに単一の項目または複数の項目が含まれているかどうかを調べるための小さなコードセグメントを書きました。私は不思議作ら

if (reportInfo.OrebodyAndPits.SelectMany(ob => ob.Pits).Count() > 1) 
{ 
    ws.Cells[row, col++].Value = "Pits"; 
} 
else 
{ 
    ws.Cells[row, col++].Value = "Pit"; 
} 

、比較をするとすぐそれが最初の項目を過ぎて列挙としてfalseを返すために十分にスマートである形式にコンパイルされるのですか?

もしそうでなければ、そうするlinq拡張メソッドを書く方法がありますか?

(。私は主に好奇心が強い私は、コードのこの作品のパフォーマンスへの影響でひどく興味がない、注意してください。)

+2

いいえ、 '.Count()'はアイテムの数を返します。 '123456789'を実行し、'> 1'の条件をチェックします。スマートな動作のために 'Skip(1).Any()'を入れてください。場合によっては、.Netは 'IEnumerable 'が実際に*配列* 'T []'または* list * 'List 'であると判断し、トラバースではなく 'Length'または' Count'を呼び出しますしかし、それは私たちが期待できることです。 –

答えて

4

いいえ、それはしません。あなたのコードは、シーケンス内のすべての項目を数えます。これは、コンパイラによってLINQ文が最適化されていないためです。

equivelentは、シーケンスが1つの以上のアイテムが含まれているかどうかをチェックするのがより効率的な方法は次のとおりです。すべての項目が残っているかどうか

reportInfo.OrebodyAndPits.SelectMany(ob => ob.Pits).Skip(1).Any(); 

これは、最初の項目をスキップした後、チェックします。

3

ソースコードを見ていない理由を知りたいのですが?

ここAny()方法です:あなたが記述のようhttps://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/Count.cs#L12

コンパイラが最適化をすることはできません。https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/AnyAll.cs#L20

はここCount()方法があります。それはカウントを求めて、数値を取得し、その数値を条件ステートメントの数値と比較します。

ただし、何らかの最適化を試みます。 Count()メソッドからわかるように、IEnumerableが既にCountプロパティをサポートしているかどうかを確認し、すべての要素を再びカウントするよりも速いため、このメソッドを使用します。利用できない場合は、全体を移動して個々に数える必要があります。

IEnumerableに少なくとも2つがあるかどうかを判断するLINQメソッド(これは単なる拡張メソッドのIEnumerable<T>)を記述したい場合は、十分に簡単なはずです。このようなもの:

public static bool AtLeastTwo<TSource>(this IEnumerable<TSource> source) 
    { 
     if (source == null) 
     { 
      throw Error.ArgumentNull(nameof(source)); 
     } 

     using (IEnumerator<TSource> e = source.GetEnumerator()) 
     { 
      e.MoveNext(); // Move past the first one 
      return e.MoveNext(); // true if there is at least a second element. 
     } 
    } 
+0

Skip + Anyは簡単で、拡張メソッドは必要ありません。 – Wazner

+0

しかし、それは尋ねられたものではありません: "もしそうでなければ、linq拡張メソッドを書く方法がありますか?" –

関連する問題