C # Différence entre First () et Find ()

Donc, je sais que Find() est uniquement une méthode List , alors que First() est une extension pour tout IEnumerable . Je sais aussi que First() renverra le premier élément si aucun paramètre n’est passé, alors que Find() lancera une exception. Enfin, je sais que First() lancera une exception si l’élément n’est pas trouvé, alors que Find() retournera la valeur par défaut du type.

J’espère que cela dissipe la confusion sur ce que je demande réellement. Ceci est une question informatique et traite de ces méthodes au niveau informatique. J’ai compris que les extensions IEnumerable ne fonctionnent pas toujours comme on pourrait s’y attendre sous le capot. Donc, voici le Q, et je veux dire d’un sharepoint vue “proche du métal”: Quelle est la différence entre Find() et First() ?

Voici un code pour fournir des hypothèses de base à utiliser pour cette question.

 var l = new List { 1, 2, 3, 4, 5 }; var x = l.First(i => i == 3); var y = l.Find(i => i == 3); 

Y a-t-il une différence de calcul entre la façon dont First() et Find() découvrent leurs valeurs dans le code ci-dessus?

Note: AsParallel() choses comme AsParallel() et AsQueryable() pour le moment.

Voici le code de la List.Find (de Reflector):

 public T Find(Predicate match) { if (match == null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); } for (int i = 0; i < this._size; i++) { if (match(this._items[i])) { return this._items[i]; } } return default(T); } 

Et voici Enumerable.First :

 public static TSource First(this IEnumerable source, Func predicate) { if (source == null) { throw Error.ArgumentNull("source"); } if (predicate == null) { throw Error.ArgumentNull("predicate"); } foreach (TSource local in source) { if (predicate(local)) { return local; } } throw Error.NoMatch(); } 

Les deux méthodes fonctionnent donc à peu près de la même manière: elles itèrent tous les éléments jusqu'à ce qu'ils en trouvent un qui corresponde au prédicat. La seule différence notable est que Find utilise une boucle for car elle connaît déjà le nombre d'éléments et First utilise une boucle foreach car elle ne la connaît pas.

First va lancer une exception quand il ne trouve rien, FirstOrDefault cependant exactement la même chose que Find (mis à part la façon dont il parcourt les éléments).

BTW Find est plutôt égal à FirstOrDefault() qu’à First() . Parce que si le prédicat de First() n’est satisfait d’aucun élément de liste, vous obtiendrez une exception. Voici ce qui retourne un dotpeek , un autre excellent remplacement de réflecteur gratuit avec certaines des fonctionnalités de ReSharper

Ici pour les méthodes d’extension Enumerable.First(...) et Enumerable.FirstOrDefault(...) :

  public static TSource FirstOrDefault(this IEnumerable source, Func predicate) { if (source == null) throw Error.ArgumentNull("source"); if (predicate == null) throw Error.ArgumentNull("predicate"); foreach (TSource element in source) { if (predicate(element)) return element; } return default(TSource); } public static TSource First(this IEnumerable source, Func predicate) { if (source == null) throw Error.ArgumentNull("source"); if (predicate == null) throw Error.ArgumentNull("predicate"); foreach (TSource element in source) { if (predicate(element)) return element; } throw Error.NoMatch(); } 

et voici pour la liste <>.

 ///  /// Searches for an element that matches the conditions defined by the specified predicate, and returns the first occurrence within the entire . ///  /// ///  /// The first element that matches the conditions defined by the specified predicate, if found; otherwise, the default value for type . ///  /// The  delegate that defines the conditions of the element to search for. is null. [__DynamicallyInvokable] public T Find(Predicate match) { if (match == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match); for (int index = 0; index < this._size; ++index) { if (match(this._items[index])) return this._items[index]; } return default (T); } 

Puisque List<> n’est indexé d’aucune façon, il doit passer par toutes les valeurs pour trouver une valeur spécifique. Par conséquent, il ne fait pas beaucoup de différence par rapport à la traversée de la liste via un énumérable (en dehors de la création d’une instance d’object auxiliaire énumérable).

Cela dit, gardez à l’esprit que la fonction Find été créée bien avant la méthode d’extension First (Framework V2.0 vs V3.5), et je doute qu’ils aient implémenté Find si la classe List<> avait été implémentée à en même temps que les méthodes d’extension.

Serait-il également vrai que l’utilisation de Find sur quelque chose qui est un énumérateur plutôt qu’une liste aura un coût potentiel de performance car un énumérateur peut ne pas avoir à récupérer la liste complète pour satisfaire le prédicat? Inversement, si vous avez déjà une liste, alors Find serait mieux.