.First vs .FirstOrDefault en C# : Quand choisir quoi ?

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction : La peur familière de tout développeur C#

\n

Imaginez la situation : vous écrivez une requête vers une base de données ou une collection en mémoire. Vous devez obtenir le premier élément qui satisfait une condition. Vous êtes sûr que cet élément existe obligatoirement. Ou pas ? C'est là que commence la danse : .First() ou .FirstOrDefault() ?

\n

Cette question est un véritable classique sur Stack Overflow avec des milliers de vues. Et ce n'est pas pour rien. Le choix entre ces deux méthodes peut faire la différence entre un code propre et prévisible, et une InvalidOperationException soudaine en Production. Mettons fin une fois pour toutes aux doutes et clarifions quand utiliser chaque méthode.

\n\n

L'essentiel en bref : Quelle est la différence ?

\n

Les deux méthodes font presque la même chose : elles retournent le premier élément d'une séquence qui satisfait une condition (ou simplement le premier élément si aucune condition n'est spécifiée). Mais il y a une différence cruciale :

\n
    \n
  • .First() — si l'élément n'est pas trouvé, elle lève une exception System.InvalidOperationException.
  • \n
  • .FirstOrDefault() — si l'élément n'est pas trouvé, elle retourne la valeur par défaut du type (null pour les types référence, 0 pour int, false pour bool, etc.).
  • \n
\n

Ça a l'air simple. Mais comme toujours, le diable se cache dans les détails.

\n\n

Quand utiliser .First() : Quand "il doit y en avoir un, un point c'est tout"

\n

Utilisez .First() lorsque votre logique métier garantit strictement que l'élément existe. S'il n'existe pas, c'est une situation exceptionnelle, une erreur dans les données ou la logique de l'application.

\n\n

Exemple 1 : Recherche par identifiant unique

\n

Si vous recherchez un utilisateur par sa clé primaire dans la base de données (par exemple, par son Id), et que vous êtes sûr que cet utilisateur existe, utilisez .First() :

\n
public class UserService\n{\n    private readonly AppDbContext _context;\n\n    public UserService(AppDbContext context)\n    {\n        _context = context;\n    }\n\n    public User GetUserById(int userId)\n    {\n        // Nous nous attendons à ce que l'utilisateur avec cet ID existe.\n        // Sinon, c'est un problème sérieux, il vaut mieux lever une exception.\n        return _context.Users.First(u => u.Id == userId);\n    }\n}
\n

Dans ce cas, l'exception est un signal d'alarme. Elle dit : "Hé, les données sont corrompues, ou quelqu'un a passé un mauvais ID". Vous attraperez cette exception plus haut dans la pile et la traiterez comme une erreur critique.

\n\n

Exemple 2 : Premier élément après un tri (garanti)

\n

Si vous triez une liste et prenez le premier élément, et que la liste contient forcément des éléments :

\n
var highestScore = players\n    .OrderByDescending(p => p.Score)\n    .First(); // Il ne peut pas y avoir 0 joueurs, nous l'avons vérifié avant
\n

Si vous avez préalablement vérifié que la collection n'est pas vide (par exemple, if (players.Any())), alors .First() est votre choix.

\n\n

Quand utiliser .FirstOrDefault() : Quand l'élément peut ne pas exister

\n

Règle d'or : Si l'absence de résultat est une situation normale et non une erreur, utilisez .FirstOrDefault().

\n\n

Exemple 1 : Recherche optionnelle

\n

Imaginez que nous recherchions une commande par son numéro, mais que la commande peut ne pas encore avoir été créée :

\n
public Order FindOrderByNumber(string orderNumber)\n{\n    // La commande peut ne pas exister. C'est normal.\n    return _context.Orders\n        .FirstOrDefault(o => o.OrderNumber == orderNumber);\n    // Retournera null si la commande n'est pas trouvée.\n}
\n

Après avoir appelé cette méthode, nous devons impérativement vérifier le résultat pour null :

\n
var order = FindOrderByNumber("CMD-12345");\nif (order != null)\n{\n    // Travailler avec la commande\n    Console.WriteLine($"Commande trouvée : {order.Id}");\n}\nelse\n{\n    Console.WriteLine("Commande non trouvée. Création d'une nouvelle.");                

Blogs

Book Recommendations