2

基礎:

IDictionary<TKey, TValue>拡張しますIEnumerable<T>

public interface IDictionary<TKey, TValue>: .., 
    IEnumerable<KeyValuePair<TKey, TValue>>
{
  ... 
} 

このクラスは、LINQの句Enumerableの実装を提供する拡張メソッドを提供しますwhere

 public static class Enumerable
 {
   ...

   public static IEnumerable<T> Where(this IEnumerable<T>, 
       bool Func<T> predicate) 
   {
       ...
   } 
 }

LINQを使用する場合、コンパイラはクエリ構文をメソッドの呼び出しに変換しますEnumerable.Where

このメソッドから返されたものが繰り返されると、コレクションのアイテムでIEnumerable<T>述語が評価されます。

対応するアイテムが結果に生成されます。

したがって、次のようなリクエスト:

var l_res = from n in List where n.key == 1 select n;

の各アイテムを繰り返し処理しListます。

Listを実装IDictionary<TKey, TValue>し、句がディクショナリのキーとして使用されるプロパティにある場合where、キーを活用して各レコードの反復を回避し、ルックアップを実行するにはどうすればよいですか?

IEnumerable<T>が実装であるかどうかをテストしてIDictionary<TKey, TValue>、使用するのに最適なリクエストを選択できることはすでにわかっています。

if(list is IDictionary<int, T>)
{
   var l_res = ((IDictionary<int, T>) list)[1]; 
}
else
{
   var l_res = from n in List where n.key == 1 select n ;
}

しかし、このようなキー付きコレクションを処理するLINQに存在する何かを見逃したかどうかを知りたいです。

注:LINQ-to0SQLプロバイダーはIQueryable<T>、同じ目的で式ツリーを使用しますが、私の質問はLINQ-to-Objectsについてです。

4

2 に答える 2

0

いいえ、あなたは何も見逃していません。LINQが認識できる唯一のキー付きコレクションはLookup<TKey, TElement>classであり、その場合でも特別なことは何もせず、Lookup<TKey, TElement>実装するという事実に落ち込むだけIEnumerable<IGrouping<TKey, TElement>>です ; 事実上、IGrouping<TKey, TElement>インターフェイスの実装を繰り返し処理しています。

IEnumerable<T>つまり、LINQ には interface 以外のインターフェイスに関する特別な知識はありません。たまたまIDictionary<TKey, TValue>インターフェースが拡張IEnumerable<KeyValuePair<TKey, TValue>>されているため、最初に操作を実行できます。

ただし、特定のルックアップ メカニズムがある型の場合は、型をスニッフィング (LINQ でよく行われること) してから、可能な場合は型固有のアクションを呼び出す必要があります。タイプスニッフィングが失敗した場合は、 で動作する実装に頼ることができますIEnumerable<T>

あなたがここでやっているように。

于 2012-12-05T19:11:16.690 に答える
0

渡された式を分析する辞書にカスタムWhereを実装できます。キー付きアクセスのように見える場合は、特別な辞書機能を使用します。

私の意見では、これは単なる理論上のオプションです。このようにしてはいけません。代わりに、フィルタリング メカニズムを調整して、ディクショナリが正しく使用されるようにする必要があります。

また、 opaqueFunc<T, bool>を他のコードに渡すと、この他のコードは、渡されたデリゲートの内部を見ることができないことに注意してください。キー付きアクセスがあることに気付くことはできません。そのため、LINQ to Objectsはこれを行うことができません。

于 2012-12-05T19:25:39.580 に答える