Les prédicats version .Net

Pour faire suite à l'article de Ludovic Chaboud-Paupi - Predicate In Action, il me semble intéressant de montrer comment on peut mettre en place ces prédicats, en .Net.

Je vais reprendre les mêmes exemples, à savoir la recherche de livres en utilisant ces 2 critères :

  • auteur : Kipling
  • titre : le titre comporte les mots "jungle" et "grand"

(dans un souci d'espace de lecture, je ne gère pas la casse des chaînes dans les exemples)

 public List<Livre> PredicatForLivre() {      List<Livre> livresTrouves = new List<Livre>();      for (int i = 0; i < CollectionLivres.Count ; i++)      {         Boolean estTrouve = false;         estTrouve =           CollectionLivres[i].Auteur.Contains("Kipling") ||           CollectionLivres[i].Titre.Contains("jungle") ||           CollectionLivres[i].Titre.Contains("grand");          if (estTrouve)          {             livresTrouves.Add(CollectionLivres[i]);          }       }      return livresTrouves; } 

Dans ce cas, on reste dans le classique avec le for. On peut commencer à simplifier un peu en passant sur un "for each" :

 public List<Livre> PredicatForEachLivre() {      List<Livre> livresTrouves = new List<Livre>();      foreach (Livre liv in CollectionLivres)      {          Boolean estTrouve = false;          estTrouve =               liv.Auteur.Contains("Kipling") ||               liv.Titre.Contains("jungle") ||               liv.Titre.Contains("grand");           if (estTrouve)           {               livresTrouves.Add(liv);           }      }      return livresTrouves; } 

Une fois de plus, rien de bien neuf sous le soleil, on évite juste la célèbre variable "i" pour parcourir la collection complète.

On peut, en revanche, utiliser le framework 4 (ou +) et utiliser un traitement parallèle pour exécuter cette fonction :

 public List<Livre> PredicatParallelForEachLivre() {      List<Livre> livresTrouves = new List<Livre>();      Parallel.ForEach(CollectionLivres, livre =>      {            Boolean estTrouve = false;            estTrouve =                 livre.Auteur.Contains("Kipling") ||                 livre.Titre.Contains("jungle") ||                 livre.Titre.Contains("grand");            if (estTrouve)            {                livresTrouves.Add(livre);            }      } );      return livresTrouves; } 

Attention toutefois, les traitements parallèles sont utiles dans certains cas, mais difficile à gérer dans d'autres (exemples : si vous exécutez des fonctions sur une base, le serveur risque de ne pas apprécier les opérations simultanées).
Ils se révèlent par contre extrêmement efficaces pour des calculs/opérations sur des objets en mémoire, à condition que l'exécution d'une itération ne dépende pas du résultat des précédentes.

Passons aux choses intéressantes de .Net pour les prédicats grâce à Linq:

 public List<Livre> PredicatLinqLivre() {      return (from livre in CollectionLivres               where livre.Auteur.Contains("Kipling") ||               livre.Titre.Contains("jungle") ||               livre.Titre.Contains("grand")               select livre).ToList(); } 

Voilà un prédicat simple via Linq, qui possède comme vous pouvez le voir une syntaxe assez proche du SQL.

A mon avis, la plus grande valeur de .Net est réservée au langage C# avec les expressions lambda. Notre exemple en utilisant ces fonctions :

 public List<Livre> PredicatLambdaLivre() {      return CollectionLivres.FindAll(                livre =>                livre.Auteur.Contains("Kipling") ||                livre.Titre.Contains("jungle") ||                livre.Titre.Contains("grand")); } 

Difficile de faire plus simple!
Il est bien-sûr possible de combiner expressions lambda, génériques et toutes les techniques habituelles. On peut par exemple créer des classes "factory" pour accéder aux données en combinant lambda, générique et entity framework.

Voilà pour le petit tour des prédicats en .Net.
Merci à Ludovic pour son article originale et ses idées d'exemples 😉

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.