web-dev-qa-db-fra.com

Trouver () contre Where (). FirstOrDefault ()

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();
        }
    }
}
117
KingOfHypocrites

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. 

166
Anthony Pegram

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. 

40
digiben

Find est seulement implémenté dans List<T>, alors que Where().FirstOrDefault() fonctionne avec tous IEnumerable<T>.

26
penartur

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.

24
Chalky

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();.

0
M Muneeb Ijaz