Select
およびWhere
方法は、LINQの中で利用可能です。すべての開発者はこれら2つの方法について何を知っているべきですか?たとえば、どちらを使用するか、どちらを使用するかなどの利点があります。
Select
およびWhere
方法は、LINQの中で利用可能です。すべての開発者はこれら2つの方法について何を知っているべきですか?たとえば、どちらを使用するか、どちらを使用するかなどの利点があります。
回答:
どこ
一致するアイテムを検索し、一致するアイテムのみを返します(フィルタリング)。
-> IEnumerable<A>
イン、IEnumerable<A>
アウト
選択する
ソース内のすべてのアイテムについて何かを返します(プロジェクション/変換)。それはアイテムそのものかもしれませんが、より一般的にはある種の予測です。
-> IEnumerable<A>
イン、IEnumerable<B>
アウト
Select
常に同じ数の要素を返します(フィルター条件に関係なく)。 Where
フィルター条件に応じて、より少ない要素を返すことができます。
Where == filter
とSelect == map
SelectとWhereは、IEnumerableに作用する2つの完全に異なる演算子です。
最初のものは射影演算子と呼ばれるもので、最後のものは制限演算子です。
そのような演算子の振る舞いを洞察する興味深い方法の1つは、その「関数型」を調べることです。
選択:(IEnumerable <T1>、Func <T1、T2>)→IEnumerable <T2> ; 入力として、T1型の要素を含むIEnumerableと、T1型の要素をT2型の要素に変換する関数の両方を受け取ります。出力は、タイプT2の要素を含むIEnumerableです。
このことから、この演算子は、入力IEnumerableの各要素に入力関数を適用し、結果を新しいIEnumerable内にラップすることで出力を生成することを容易に推測できます。
いくつかの数学のような表記法を使用して、それは入力(a、b、c、...)として取得します:IEnumerable <T1>およびf:T1→T2および(f(a)、f(b)、f(c)を生成します、...):IEnumerable <T2>
場所:(IEnumerable <T1>、Func <T1、bool>)→IEnumerable <T1> ; これは、T1型の要素を含むIEnumerableとT1の述語(つまり、T1型の入力に対してブール結果を生成する関数)を取ります。出力は、T1型の要素を含むIEnumerableでもあることがわかります。
今回は、要素への述語の適用結果に応じて、入力IEnumerableの要素が出力IEnumerableに存在すると推測します。これにオペレーター名のセマンティクスを追加すると、述語のアプリケーションでtrueと評価される要素のみを入力から取得することにより、出力IEnumerableが確実に生成されます。
関数型プログラミングのバックグラウンドを持つ人々は通常、このように考えます。それはあなたがそのタイプを見ることだけでオペレーターが何をするかを推測する(または少なくとも推測する)ことを可能にします!
演習として、ドキュメントを見る前に、IEnumerablesでLINQによって導入された他の演算子を見て、それらの動作を推測してみてください。
Whereおよびselect拡張メソッドの実装方法を知っている場合は、それが何をしているかを予測できます... whereおよびselect拡張メソッドを実装してみました...あなたはそれを見ることができます...
実装場所::
public static IEnumerable<Tsource> Where<Tsource> ( this IEnumerable<Tsource> a , Func<Tsource , bool> Method )
{
foreach ( var data in a )
{
//If the lambda Expression(delegate) returns "true" Then return the Data. (use 'yield' for deferred return)
if ( Method.Invoke ( data ) )
{
yield return data;
}
}
}
実装を選択::
public static IEnumerable<TResult> Select<TSource , TResult> ( this IEnumerable<TSource> a , Func<TSource , TResult> Method )
{
foreach ( var item in a )
{
//Each iteration call the delegate and return the Data back.(use 'yield' for deferred return)
yield return Method.Invoke ( item );
}
}
私の実装はどのコレクションでも問題なく動作しますが、Microsoftが実装した拡張メソッドとは異なります。これらは式ツリーを使用して同じものを実装しているためです。
Select itの場合、新しい構造のIEnumerableにマップできます。
A.Select(x=>new X{UID=x.uid, UNAME=x.uname})
//input as [IEnumerable<A>] --------> return output as [IEnumerable<X> ]
Where()はIEnumerableのフィルターとして機能し、where句に基づいて結果を返します。
A.Where(x=>x.uid!=0) //input as [IEnumerable<A>] --------> return output as [IEnumerable<A> ]