Je vois souvent des personnes utiliser Where.FirstOrDefault()
pour effectuer une recherche et saisir le premier élément. Pourquoi ne pas simplement utiliser Find()
? Y a-t-il un avantage pour l'autre? Je ne pouvais pas faire la différence.
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();
}
}
}
Où est la méthode Find
sur IEnumerable<T>
? (Question rhétorique.)
Les méthodes Where
et FirstOrDefault
s'appliquent à plusieurs types de séquences, notamment List<T>
, T[]
, Collection<T>
, etc. Toute séquence implémentant IEnumerable<T>
peut utiliser ces méthodes. Find
est disponible uniquement pour le List<T>
. Les méthodes généralement plus applicables sont alors plus réutilisables et ont un impact plus important.
Je suppose que ma prochaine question serait pourquoi ont-ils ajouté la découverte? C'est un bon conseil. La seule chose à laquelle je peux penser est que FirstOrDefault pourrait renvoyer une valeur par défaut différente de null. Sinon, cela semble être un ajout inutile
Find
sur List<T>
est antérieur aux autres méthodes. List<T>
a été ajouté avec les génériques dans .NET 2.0 et Find
faisait partie de l'API de cette classe. Where
et FirstOrDefault
ont été ajoutés comme méthodes d'extension pour IEnumerable<T>
avec Linq, une version ultérieure de .NET. Je ne peux pas affirmer avec certitude que si Linq existait avec la version 2.0, Find
n'aurait jamais été ajouté, mais c'est sans doute le cas pour de nombreuses autres fonctionnalités fournies dans des versions antérieures de .NET qui sont devenues obsolètes ou redondantes.
Je viens de le découvrir aujourd'hui en effectuant des tests sur une liste d'objets de 80K et que Find()
peut être jusqu'à 1000% plus rapide que d'utiliser une Where
avec FirstOrDefault()
. Je ne savais pas cela avant de tester une minuterie avant et après tout. Parfois, c'était le même temps, sinon c'était plus rapide.
Find
est seulement implémenté dans List<T>
, alors que Where().FirstOrDefault()
fonctionne avec tous IEnumerable<T>
.
Il existe une différence très importante si Entity Framework est la source des données: Find
trouvera les entités dans l'état 'ajouté' qui ne sont pas encore persistées, mais Where
ne le fera pas. C'est par conception.
en plus d'Anthony answer Where()
parcourez tous les enregistrements, puis renverra les résultats, alors que Find()
n'a pas besoin de parcourir tous les enregistrements si le prédicat correspond à un prédicat donné.
alors disons que vous avez la liste List of Test ayant les propriétés id
et 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);
Donnera la sortie de 2
, et seulement 2 visites Trouver nécessaire pour donner un résultat, mais si vous utilisez Where().FirstOrDefault()
, nous visiterons tous les enregistrements et nous obtiendrons des résultats.
Ainsi, lorsque vous savez que vous souhaitez uniquement obtenir le premier résultat des enregistrements de la collection, Find()
sera plus approprié que Where().FirtorDefault();
.