5

重複の可能性:
Collection<T> と List<T> の違いインターフェイスで何を使用する必要がありますか?

このメソッドを考えてみましょう。返される変数myVarは ですがList<T>、メソッドの戻り値の型はMyMethod()ですIEnumerable<T>

public IEnumerable<T> MyMethod(string stuff)
{
     var myVar = new List<T>();
     //do stuff

     return myVar;
}

基本的に、私が知りたいのはmyVar、別の型として返してよいかということです。

具体的には、私の状況に関しては、「do stuff」は a を通過し、その中のアイテムをオブジェクトのリストにDataRow割り当てます。DataRow他の場所でも同様の状況がICollectionあり、IList戻り値の型があります。

IEnumerableどちらかまたはどちらかを返したい理由ICollectionは、必要以上に返さないようにするためです。しかし同時に、これにより呼び出し元は、List必要に応じて戻り値を に変換できます。

Listただし、メソッドの戻り値の型ではなく、 return ステートメントが を返すのは奇妙に思えます。これは通常の慣行ですか?これを行うと何か問題がありますか?

明確化(だまされたコメントへの対応):

明確にするために、私が興味を持っているのは、本体の return ステートメントが を返しても問題ないかどうかですList<T>が、メソッドヘッダーの戻り値の型はIEnumerable、またはおそらくICollectionCollectionなどです...本体とは異なるものリターンステートメント。

4

4 に答える 4

6

何も問題がないだけでなく、実際には良い習慣です。厳密に必要なものだけを公開してください。そうすれば、呼び出し元はメソッドが を返すという事実に依存できないためList<T>、何らかの理由で別のものを返すように実装を変更する必要がある場合でも、契約を破ることはありません。ただし、メソッドが実際に返すものについて (誤って) 仮定を行った場合、呼び出し元のコード壊れる可能性があります。

于 2012-04-16T22:32:00.877 に答える
3

型を返す理由IEnumerable<T>は、呼び出し元がリストを変更できないようにするためです (リストにキャストし直す必要はありません)。すべて (ほとんど?) の拡張メソッドがIEnumerable<T>引数を取ることに気付いた場合は、拡張メソッドがリストを変更しないことがわかります。

次に、List<T>から継承しIEnumerable<T>ます。

編集: Thomas がコメントで説明したように、 は呼び出し元によってIEnumerable<T>a にキャストバックされ、変更される可能性があります。List<T>主な目的が読み取り専用にすることである場合は、リストを として返すことができますmyVar.AsReadOnly()。しかし、タイプはReadOnlyCollection<T>.

于 2012-04-16T22:28:39.097 に答える
2

何も問題はありません。

実際に具体的なクラスを返すことは、「インターフェイスを返す」要件を満たす唯一の方法です。

特定のクラスの知識をコードの呼び出しに忍び込ませると、欠点が生じる可能性があります ( List<T> r = (List<T>)MyMethod("ff"))。しかし、結果を(想定どおり)インターフェースとして扱う場合は問題ありません。

于 2012-04-16T22:28:06.920 に答える
1

List<T>実装の詳細に依存する呼び出し元が にキャストできるため、これは最適ではないと思います。などのマスキングを追加しSelect(x=>x)ます。

動的に型付けされた呼び出し元は、リストを にキャストしたことにさえ気付かない場合がありますIEnumerable<T>。彼にとってそれは単純List<T>です。

呼び出し元がクラスの内部状態を変更できるため、内部パーマネントList<T>を返すことは非常に間違っています。IEnumerable<T>ただし、呼び出しのたびにの新しいインスタンスを返すため、List<T>それは他の場所では使用されないため、この引数は例には適用されません。

于 2012-04-16T22:37:22.827 に答える