Найти() 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();
        }
    }
}

Ответ 1

Где метод Find на IEnumerable<T>? (Риторический вопрос.)

Методы Where и FirstOrDefault применимы к нескольким типам последовательностей, включая List<T>, T[], Collection<T> и т.д. Любая последовательность, реализующая IEnumerable<T>, может использовать эти методы. Find доступен только для List<T>. Методы, которые обычно более применимы, затем более многоразовые и имеют больший эффект.

Я предполагаю, что мой следующий вопрос будет заключаться в том, почему они добавили находку вообще. Это хороший совет. Единственное, о чем я могу думать, это то, что FirstOrDefault может вернуть другое значение по умолчанию, отличное от нуля. В противном случае это просто кажется бессмысленным добавлением

Find on List<T> предшествует другим методам. List<T> был добавлен с generics в .NET 2.0, а Find был частью API для этого класса. Where и FirstOrDefault были добавлены в качестве методов расширения для IEnumerable<T> с Linq, который является более поздней версией .NET. Я не могу с уверенностью сказать, что если Linq существовал с выпуском 2.0, который Find никогда бы не был добавлен, но это, возможно, относится ко многим другим функциям, которые появились в более ранних версиях .NET, которые были устаревшими или избыточными более поздними версиями.

Ответ 2

Я только что узнал сегодня, выполняя некоторые тесты в списке 80K-объектов и обнаружил, что Find() может быть на 1000% быстрее, чем с помощью Where с FirstOrDefault(). Я не знал этого до тестирования таймера до и после каждого. Иногда это было то же самое время, иначе это было быстрее.

Ответ 3

Find только реализован в List<T>, а Where().FirstOrDefault() работает со всеми IEnumerable<T>.

Ответ 4

Существует очень важная разница, если источником данных является Entity Framework: Find найдет объекты в состоянии "добавлено", которые еще не сохранены, но Where не будет. Это по дизайну.

Ответ 5

в дополнение к Anthony answer Where() просмотреть все записи, а затем вернуть результат (ы), в то время как Find() не нужно проходить через все записи, если предикат соответствует заданному предикату.

поэтому скажите, что у вас есть класс List of Test, имеющий свойства 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 посещения. Найти нужно, чтобы дать результат, но если вы используете Where().FirstOrDefault() мы будем посещать все записи, а затем получаем результаты.

Итак, когда вы знаете, что только первый результат из записей в коллекции Find() будет более подходящим, тогда Where().FirtorDefault();