2009-03-25 10 views
8

SearchServiceレイヤーに、特定の文字列で始まるすべての車を検索するメソッドがあるとします。私のサービスはどのインターフェースを返すべきですか? IQueryable、IList、IEnumerable?

public static class Searcher{ 
    public IAnInterface<Car> CarsStartingWith(string startWith){ 
     //magic 
    } 
} 

私のサービスで使用するインターフェイスは何ですか?
IQueryableは、残りのアプリケーションで素晴らしい流体インターフェイスをレンダリングできます。
IEnumerableには、怠惰な側面があります。
IListが最も実用的です。私はすべてのサービスが一貫性のために同じインタフェースを返す持ちたい

は非常に簡単に全体のことになります。それは枠組みの中でより多くの中心的な場所を持っているためにも親しみを提供しながら、私は、それを必要とするもののために汎用性を提供し、IEnumerableを選ぶだろう
いるICollectionは、多分あまりにも選択肢かもしれないが、それはちょうどので、少し...

+0

ここではほぼ重複した議論があります:http://stackoverflow.com/questions/396513/should-parameters-returns-of-collections-be-ienumerablet-or-t –

答えて

2

すべてのサービスが同じインターフェイスを返すようにしたい場合は、おそらくIEnumerable<>に行きます。

あなたの発信者がIQueryableに変換したり、必要に応じて、Listを作成するための十分な簡単なことでしょう:あなたがいないと、重大な理由がない限り

IEnumerable<Car> cars = Searcher.CarsStartingWith("L"); 
var carsList = cars.ToList(); 
var queryableCars = cars.AsQueryable(); 
+0

完全に同意します。必要な最小限の契約を常に使用する必要があります。 IEnumerable は、あなたが実証したように、多くのBCLタイプによって消費されるか変換されます。 –

+0

真。私はIEnumerableを返すことにしました。また、IListが特定のケースでより意味をなさない場合は、これらのメソッドを群衆から目立たせるために命名規則を使用します。 –

+4

'IEnumerable 'を返す問題は、それを 'IQuerable 'に変換することを決定した場合です。あなたはもはやDBに対してクエリを実行しませんが、メモリ内のオブジェクトに対してクエリを実行します。 James Curranが指摘しているように、 'IQueryable'は少し重いですが、ほとんどのシナリオでは、クエリ可能なセットバックを提供する方が、消費者がIEnumerableにキャストしたいかどうかを決定することができます。 –

3

を提供していますまだLINQのようなものにこだわっていない人たちに。

+0

私はIEnumerableが好きです。それはCountメソッドです。私はそれがどれくらいあるかを知らないために怠け者であることが固有であることを知っていますが、Countプロパティはあなたが何度も必要なものです! –

+0

LINQはIEnumerableのCount拡張メソッドを提供します。 –

+0

@JeffオリジナルがIQueryable(それは検索され、カウントされる)だったら良い考えではありません。 – eglasius

2

IQueryableにはかなり重い要件があります。たとえば、配列を返すことはできません。

通常、私の場合、IEnumerableまたはIListのいずれかの選択は、通常、標準ケースで実装する方が簡単です。

+0

これまでの私と同じです。しかし私は私のプログラミングスタイルで少しずつ一貫しています。流体インターフェイスは通常非常に読みやすく見えるので、私はIQueryableを投げ込むと思いました。 –

2

短い回答:それは依存します。

長い答えは:あなたのクライアントコードが必要になるだろう豊かな型を返します。遅延ロードを必要としない場合、IListはほとんどの場合動作します。 Linqを使用して、IListまたはIEnumerableに対してクエリを実行することはできます。遅延ロードが必要な場合は、IEnumerableまたはIQueryableを使用します。

サイドノート:すべてのサービスで同じインターフェースを返すことは貴重な目標のように見えるかもしれませんが、クライアントの使用パターンが異なると、異なるインターフェースを返すことができます。

+0

true、おそらく命名規則はレイジー/ノン・レイジーで面白いかもしれません。 –

+0

私は別の方法で議論するだろう。 IListはIEnumerable以上の方法を提供しているため、追加、削除、索引付けなどの追加メソッドが必要な場合を除き、遅延評価に関係なくIEnumerableを選択する必要があります。 –

2

は必ずIEnumerableで行きます。その後、yield returnでゲッターを実装することができます。

IQueryableは魚の全く異なるやかんです。典型的なメモリ内のコンテナの代わりとして、あなたが気軽に実装するものではありません。

IEnumerableとその他の間には大きな違いがあります。読み取り専用です。

+0

IEnumerableに戻り値をキャストしても読み取り専用にならないため、呼び出された側で再度キャストすることができます。読み取り専用の場合は、結果を読み取り専用のコレクション(たとえばList(T).AsReadOnlyを使用)でラップしてから返します。私は通常、IList(T)またはICollection(T)を返します。 – Joe

+1

もちろん、私はそれが読み込み専用になるように静的に型付けされているということです。 「フィールドを非公開にすることは何の意味もありません - とにかく彼らを得るためにリフレクションを使うことができます」と言うかもしれません。 –

3

次のように親指の私のルールは次のとおりです。

私は日常のコアアルゴリズムを取ると私は降伏リターンを使用することができる方法でそれをリファクタリングすることができます機会が今まであった場合、私がIEnumerableを< Tと一緒に行きます>。

たとえば、現在の実装で配列またはリスト<T>が内部的に使用されていますが、少なくとも理論的には、遅延評価を行うために内部的に再加工することができます。 IEnumerable <T>を返します。

私は、IEnumerable <T>を返すことの利益が間違いなくそれを使用することの価値があることがわかりました。

しかし、本質的にアルゴリズムが返される前に完全に評価する必要がある場合(稀ですが、起こります)、私はIList <T>に行きます。基本的に、私がすでにそれを計算しているなら、私はそれを返すでしょう。 IList <T>はIEnumerable <T>を実装しているため、LINQ関連のユースケースはすべて機能しますが、遅延評価は失われます。私がすでに評価を余儀なくされているのであれば、それは問題ではありません。

IQueryableを返すことはめったにありません。このインターフェイスを使用する唯一の時間は、クエリ可能なデータアクセスレイヤーなどを直接作成する場合です。これを使用するオーバーヘッドは、ほとんどの場合、利益に値するものではありません。

しかし、あなたの目標が常に1つのインターフェイスを使用することです(私はこの目標に必ずしも同意しません)。IEnumerable <T>に固執します。

0

戻り値の型としてIQueryableを使用している場合、漏れ抽象を持つサービスレイヤがあります。

関連する問題