私はよくWhere.FirstOrDefault()
を使用して検索を行い、最初の要素を取得する人々を目にします。なぜFind()
を使用しないのですか?他に利点はありますか?違いがわからなかった。
namespace LinqFindVsWhere
{
class Program
{
static void Main(string[] args)
{
List<string> list = new List<string>();
list.AddRange(new string[]
{
"item1",
"item2",
"item3",
"item4"
});
string item2 = list.Find(x => x == "item2");
Console.WriteLine(item2 == null ? "not found" : "found");
string item3 = list.Where(x => x == "item3").FirstOrDefault();
Console.WriteLine(item3 == null ? "not found" : "found");
Console.ReadKey();
}
}
}
IEnumerable<T>
のFind
メソッドはどこにありますか? (修辞的質問。)
Where
およびFirstOrDefault
メソッドは、List<T>
、T[]
、Collection<T>
など、複数の種類のシーケンスに対して適用できます。IEnumerable<T>
を実装するシーケンスは、これらのメソッドを使用できます。 Find
は、List<T>
でのみ使用可能です。一般的に適用可能なメソッドは、より多くの再利用可能であり、より大きな影響があります。
私の次の質問は、なぜ彼らが発見を追加したのかということだと思います。それは良いヒントです。私が考えることができる唯一のものは、FirstOrDefaultがnull以外の異なるデフォルト値を返すことができるということです。さもなければ、それは無意味な追加のように見える
List<T>
のFind
は、他のメソッドよりも前のものです。 List<T>
は.NET 2.0のジェネリックで追加され、Find
はそのクラスのAPIの一部でした。 Where
およびFirstOrDefault
は、Linqを使用したIEnumerable<T>
の拡張メソッドとして追加されました。これは.NETバージョンです。 Linqが2.0リリースに存在する場合、Find
が追加されることはなかったとは断言できませんが、それは間違いなく、以前の.NETバージョンに含まれていた、後から廃止または冗長になった他の多くの機能の場合ですバージョン。
私は今日、80Kオブジェクトのリストでいくつかのテストを行い、Find()
がFirstOrDefault()
でWhere
を使用するよりも最大1000%高速であることがわかりました。私は、すべての前後にタイマーをテストするまで、それを知りませんでした。時々それは同じ時間でしたが、そうでなければより高速でした。
Find
はList<T>
で 実装済み のみですが、Where().FirstOrDefault()
はすべてのIEnumerable<T>
で機能します。
データのソースがEntity Frameworkの場合、非常に重要な違いがあります。Find
は、まだ追加されていない 'added'状態のエンティティを検出しますが、Where
は検出しません。これは仕様です。
anthonyの回答に加えて、Where()
すべてのレコードを訪問し、結果を返しますが、Find()
は、指定された述語と述語が一致する場合、すべてのレコードを横断する必要はありません。
id
プロパティとname
プロパティを持つテストクラスのリストがあるとします。
List<Test> tests = new List<Test>();
tests.Add(new Test() { Id = 1, Name = "name1" });
tests.Add(new Test() { Id = 2, Name = "name2" });
tests.Add(new Test() { Id = 3, Name = "name3" });
tests.Add(new Test() { Id = 4, Name = "name2" });
var r = tests.Find(p => p.Name == "name2");
Console.WriteLine(r.Id);
2
の出力を提供し、2 visitsはresultを提供するために必要な検索を行いますが、Where().FirstOrDefault()
を使用する場合、すべてのレコードを訪問し、結果を取得します。
そのため、コレクションのレコードから最初の結果のみが必要なことがわかっている場合は、Find()
がWhere().FirtorDefault();
より適切です