iは、に使用されるデフォルトのイテレータは拡張メソッドがとを選択していることに気づきました。私は適切にコードを読めば、このようなカウント()とToListメソッドなど他のいくつかの拡張メソッドを、(原因)遅く実行します。WhereSelectArrayIteratorがICollectionを実装していないのはなぜですか? <strong>WhereSelectArrayIterator</strong> - - <strong>いるICollection</strong>インタフェースを実装していない反射板を通じて<strong>System.Linq.Enumerable</strong>を見て
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
{
// code above snipped
if (source is List<TSource>)
{
return new WhereSelectListIterator<TSource, TResult>((List<TSource>) source, null, selector);
}
// code below snipped
}
private class WhereSelectListIterator<TSource, TResult> : Enumerable.Iterator<TResult>
{
// Fields
private List<TSource> source; // class has access to List source so can implement ICollection
// code below snipped
}
public class List<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable
{
public List(IEnumerable<T> collection)
{
ICollection<T> is2 = collection as ICollection<T>;
if (is2 != null)
{
int count = is2.Count;
this._items = new T[count];
is2.CopyTo(this._items, 0); // FAST
this._size = count;
}
else
{
this._size = 0;
this._items = new T[4];
using (IEnumerator<T> enumerator = collection.GetEnumerator())
{
while (enumerator.MoveNext())
{
this.Add(enumerator.Current); // SLOW, CAUSES ARRAY EXPANSION
}
}
}
}
}
を私は疑いを確認した結果でこれをテストしてみました:
いるICollection:2388.5222ミリ
IEnumerabl E:3308.3382ミリ
ここでは、テストコードです:
// prepare source
var n = 10000;
var source = new List<int>(n);
for (int i = 0; i < n; i++) source.Add(i);
// Test List creation using ICollection
var startTime = DateTime.Now;
for (int i = 0; i < n; i++)
{
foreach(int l in source.Select(k => k)); // itterate to make comparison fair
new List<int>(source);
}
var finishTime = DateTime.Now;
Response.Write("ICollection: " + (finishTime - startTime).TotalMilliseconds + " ms <br />");
// Test List creation using IEnumerable
startTime = DateTime.Now;
for (int i = 0; i < n; i++) new List<int>(source.Select(k => k));
finishTime = DateTime.Now;
Response.Write("IEnumerable: " + (finishTime - startTime).TotalMilliseconds + " ms");
は、私は何かが足りないか、これは、フレームワークの将来のバージョンで修正される予定は?
ありがとうございました。
ありがとうございます - それはあらかじめサイズを知ることを妨げる厄介な述語です。私は、プロセスリストのサイズを変更せずにプロセスリストを頻繁に実行し、おそらくwhereSelectIterratorがSelectIterratorのサブクラスであり、icollectionを実装できるケースを作成します。とにかく、もう一度、ありがとう。 –
実際には、スクラッチ、逆:WhereSelectIterratorは親クラスであり、SelectIterratorはICollectionを実装するサブクラスでなければなりません –