.Net がReflector を使用してメソッドをList
実装する方法を簡単に確認できます。Find
Public Function Find(ByVal match As Predicate(Of T)) As T
If (match Is Nothing) Then
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match)
End If
Dim i As Integer
For i = 0 To Me._size - 1
If match.Invoke(Me._items(i)) Then
Return Me._items(i)
End If
Next i
Return CType(Nothing, T)
End Function
両方の実装の唯一の違いは、このロジックをループ内にインライン化Find
する代わりに への呼び出しが必要なことです。match
興味深いことに、この単純なパフォーマンス:
var persons = new List<Person>();
for (int i = 0; i < 100; i++)
{
persons.Add(new Person { ID = i });
}
GC.Collect();
var sw = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
persons.Find(person => person.ID == i % 100);
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
GC.Collect();
sw = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
for (int j = 0; j < 100; j++)
{
if (persons[j].ID == i % 100)
{
break;
}
}
}
sw.Stop();
Console.WriteLine(sw.Elapsed);
Find
を使用してリストをクエリするのに必要な合計時間は05.7990078秒です。ループ
を使用してリストを照会するのに必要な合計時間は 06.3551074秒です。
この結果は、いくつかの実行で一貫しているようです。
編集- の利点の説明が見つかりましたFind
:
Find
は、各反復で基になる配列に直接アクセスするため、より高速に動作します。ループはList
インデクサーを介してアクセスします。これには、アクセスごとにインデックスの検証が必要です。
Public Default Property Item(ByVal index As Integer) As T
Get
If (index >= Me._size) Then
ThrowHelper.ThrowArgumentOutOfRangeException
End If
Return Me._items(index) // _items is the underlying array.
End Get