Améliorer l’Exception due à des clés dupliquées de la méthode ToDictionary

Slim Ayache
YounitedTech
Published in
3 min readJul 5, 2019

L’Exception du framework

Considérons ce code simple :

Comme nous pouvons voir ce code renverra une exception due à des identifiants dupliquées dans notre liste que nous avons choisi d’utiliser en tant que clés dans le dictionnaire à créer. Le problème c’est que le message d’exception est (très) loin d’être précis. Il nous aide nullement dans l’identification de la (ou les) clés dupliquée(s).

tout ce que nous aurons, est ce message !

Comment pouvons nous l’améliorer ?

Ma tête en pleine réflexion

La nouvelle Exception

Cette exception héritera de ArgumentException et sera utilisée au lieu de cette dernière dans le cas des clés dupliquée. Nous allons voir son utilisation dans ce qui suit.

La première solution : le grouping

Une des solutions les plus directes est de faire un grouping avec la clé.
Nous pouvons utiliser ce code dans le block catch pour renvoyer la liste de toutes les clés dupliquées dés la première erreur rencontrée:

L’autre proposition : la méthode d’extension

En nous inspirant de l’implémentation de la classe Enumerable dans le framework .Net Core, et surtout de l’extension qui nous intéresse: ToDictionary, nous pouvons voir que cette dernière ne fait qu’appeler de façon générique une boucle qui parcourt les éléments de l’enumerable pour les ajouter à un dictionnaire de sortie.

Implémentation de ToDictionary dans le framework .Net Core

Nous allons ajouter notre propre extension ToDictionaryWithDetailedException comme suivant :

Nous pouvons voir que l’utilisation de cette méthode d’extension simplifie largement le code.

Critique de la deuxième solution

Le pour :

  • Simple dans l’utilisation:
    Remplacer ToDictionary avec ToDictionaryWithDetailedException change très peu le code existant. Elle peut être aisément partagée et distribuée dans un nuget local.
  • Générique:
    Tout comme ToDictionary cette méthode est générique.
  • Performante:
    - Une seule boucle suffit pour retrouver une exception ou une erreur.
    - L’utilisation de ContainsKey a une complexité faible en O(1).
    - L’utilisation d’un StringBuilder améliore la création du message à partir d’une certaine taille.
  • Note tout:
    l’Occurrence de chaque clé dupliquée est bien apparente dans le message.

Le contre :

  • Les clés peuvent être des Objects complexes:
    Si ToString() n’est pas implémenté dans l’object “Clé” on finira avec un message inexploitable.
  • les grandes listes:
    ToDictionaryWithDetailedException termine toute la boucle, la ou ToDictionary s’arrête à la premiere clé dupliquée. Si notre liste comporte 100.000 éléments avec une même clé, il faut s’attendre à un parcours entier qui générera une message d’exception avec 100.000 clés.
  • Ajoute un temps de traitement:
    La méthode d’extension ajoute un traitement supplémentaire au début de chaque ajout et ne devrait donc pas être utilisée comme un remplacement automatique à ToDictionary.
  • Le séparateur ?:
    Le séparateur `;` est-il le meilleur qu’on puisse utiliser ?
    Une autre façon de faire serait d’utiliser AggregateException en enregistrant chaque clé manquante dans une InnerException à part et ainsi ne plus utiliser un simple message. mais cette méthode a aussi ses défauts.
  • La duplication du code:
    Finalement, notre méthode d’extension est en quelque sorte la duplication du code du framework. Si ce dernier change, même si cela est peu probable, il faudra adapter, voire supprimer notre code.

Ne pas oublier

Si notre code lance une exception avec ToDictionary c’est qu’avant tout, nos données ne sont pas bonnes ! Il faut d’abord réfléchir à corriger la source de notre Enumerable car c’est l’origine de tous les maux. Utiliser un try-catch, avec ou sans l’amélioration du message de l’exception est le dernier recours pour la gestion de l’anomalie.

--

--

Slim Ayache
YounitedTech

Software developer (and I like it). I Speak AR, FR, EN. Interests in photography, music, books and one billion other things.