web-dev-qa-db-ja.com

Find()vs. Where()。FirstOrDefault()

私はよく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();
        }
    }
}
137

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バージョンに含まれていた、後から廃止または冗長になった他の多くの機能の場合ですバージョン。

185
Anthony Pegram

私は今日、80Kオブジェクトのリストでいくつかのテストを行い、Find()FirstOrDefault()Whereを使用するよりも最大1000%高速であることがわかりました。私は、すべての前後にタイマーをテストするまで、それを知りませんでした。時々それは同じ時間でしたが、そうでなければより高速でした。

42
digiben

FindList<T>実装済み のみですが、Where().FirstOrDefault()はすべてのIEnumerable<T>で機能します。

28
penartur

データのソースがEntity Frameworkの場合、非常に重要な違いがあります。Findは、まだ追加されていない 'added'状態のエンティティを検出しますが、Whereは検出しません。これは仕様です。

27
Chalky

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();より適切です

1
M Muneeb Ijaz