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