私のコードでは、 を複数回使用する必要がありIEnumerable<>
、その結果、「 の複数の列挙の可能性があります」という ReSharper エラーが発生しますIEnumerable
。
サンプルコード:
public List<object> Foo(IEnumerable<object> objects)
{
if (objects == null || !objects.Any())
throw new ArgumentException();
var firstObject = objects.First();
var list = DoSomeThing(firstObject);
var secondList = DoSomeThingElse(objects);
list.AddRange(secondList);
return list;
}
objects
パラメータを に変更して、複数の列挙の可能性を回避することはできますList
が、その場合、処理できる最高のオブジェクトを取得できません。- 他にできることは、メソッドの先頭で を に
IEnumerable
変換することです。List
public List<object> Foo(IEnumerable<object> objects)
{
var objectList = objects.ToList();
// ...
}
しかし、これはただ気まずいだけです。
このシナリオではあなたはどうしますか?
ベストアンサー1
をパラメータとして取る場合の問題IEnumerable
は、呼び出し元に「これを列挙したい」と伝えることです。列挙する回数は伝えません。
オブジェクト パラメータを List に変更して、複数の列挙を回避することはできますが、その場合、処理できる最高のオブジェクトを取得できません。
最も高いオブジェクトを取得するという目標は崇高ですが、想定の余地が多すぎます。このメソッドに LINQ to SQL クエリを渡して、それを 2 回列挙する (毎回異なる結果になる可能性がある) ことを本当に望みますか?
ここで意味が欠けているのは、メソッドの詳細を読む時間がないかもしれない呼び出し元が、反復処理は 1 回だけであると想定し、高価なオブジェクトを渡す可能性があることです。メソッド シグネチャではどちらの場合も示されていません。
メソッド シグネチャをIList
/に変更することでICollection
、少なくとも呼び出し元に対して期待していることが明確になり、コストのかかる間違いを回避できます。
そうしないと、メソッドを見るほとんどの開発者は、反復処理が 1 回だけであると想定するかもしれません。 を取ることが非常に重要な場合は、メソッドの先頭でIEnumerable
を行うことを検討する必要があります。.ToList()
.NET に、Add/Remove などのメソッドのない IEnumerable + Count + Indexer のインターフェイスがないのは残念です。これがこの問題を解決するのではないかと思います。