web-dev-qa-db-ja.com

IEnumerableからIReadOnlyCollection

私はIEnumerable<Object>を持っていて、パラメーターとしてメソッドに渡す必要がありますが、このメソッドはIReadOnlyCollection<Object>を取ります

IEnumerable<Object>IReadOnlyCollection<Object>に変換することは可能ですか?

30
Mohamed Badr

1つの方法は、リストを作成し、それに対して AsReadOnly() を呼び出すことです。

_IReadOnlyCollection<Object> rdOnly = orig.ToList().AsReadOnly();
_

これにより、_ReadOnlyCollection<object>_を実装する _IReadOnlyCollection<Object>_ が生成されます。

注:_List<T>_は_IReadOnlyCollection<T>_も実装しているため、AsReadOnly()の呼び出しはオプションです。 ToList()の結果を使用してメソッドを呼び出すことは可能ですが、私はAsReadOnly()を使用することをお勧めします。これにより、私のコードの読者は、私が呼び出しているメソッドに意図がないことがわかるようになりますリストを変更します。もちろん、私が呼び出しているメソッドのシグネチャを見ても同じことがわかりますが、それを明示するのはいいことです。

32
dasblinkenlight

他の答えは、コレクションをtruly読み取り専用タイプでラップする方向に舵を切るように見えるので、これを追加します。

呼び出し元が非常に怖がって、_IEnumerable<T>_- takeingメソッドが悪意を持ってキャストしようとする可能性がある状況を、私はめったに見たことはありません_IEnumerable<T>_ Listまたはその他の変更可能な型に戻り、変更を開始します。 キューオルガンミュージックと邪悪な笑い声!

いいえ。使用しているコードがリモートで合理的である場合でも、読み取り機能しか持たない型(_IEnumerable<T>_、_IReadOnlyCollection<T>_...)を要求すると、読み取りのみが行われます。

ToList()を使用して、それで完了します。

補足として、問題のメソッドを作成している場合は、一般に_IEnumerable<T>_以下の値を要求することをお勧めします。これは、「大量の項目を読み取ってほしい」ことを示します。 Countが必要かどうか、または複数回列挙する必要があるかどうかは、実装の詳細であり、確かに変更される傾向があります。複数の列挙が必要な場合は、次のようにします。

_items = items as IReadOnlyCollection<T> ?? items.ToList(); // Avoid multiple enumeration
_

これにより、所属する場所の責任が(可能な限りローカルに)維持され、メソッドシグネチャがクリーンになります。

一方、returningアイテムの束の場合、_IReadOnlyCollection<T>_を返すことを好みます。どうして?目標は、合理的な期待を満たすものを発信者に与えることです-これ以上でもそれ以下でもありません。これらの期待は、通常、コレクションが具体化され、Countが既知であること、正確には_IReadOnlyCollection<T>_が提供するもの(そして単純な_IEnumerable<T>_は提供しないもの)です。これ以上具体的ではないため、契約は期待に一致し、メソッドは基になるコレクションを自由に変更できます。 (対照的に、メソッドが_List<T>_を返す場合、リストにインデックスを付けて変更する必要があるのはどのようなコンテキストがあるのか​​不思議に思われます。答えは通常「なし」です。)

2
Timo

Dasblinkenlightの回答の代わりに、呼び出し側がList <T>にキャストしないようにするには、orig.ToList().AsReadOnly()を実行する代わりに、次の方法が適しています。

ReadOnlyCollection<object> rdOnly = Array.AsReadOnly(orig.ToArray());

メソッド呼び出しの数は同じですが、1つは戻り値で呼び出されるのではなく、もう1つをパラメーターとして受け取ります。

2
Neo