65 votes

Pourquoi l'exception NotImplementedException existe-t-elle ?

J'espère donc que quelqu'un pourra me donner une justification raisonnable pour expliquer pourquoi les choses sont telles qu'elles sont.

NotImplementedException. Vous vous moquez de moi, n'est-ce pas ?

Non, je ne vais pas prendre un coup bas en disant "Attendez, la méthode est implémentée - elle lève une NotImplementedException". Oui, c'est vrai, vous devez implémenter la méthode pour qu'elle lève une NotImplementedException (contrairement à un appel de fonction virtuelle pure en C++ - ça a du sens !) Même si c'est plutôt amusant, il y a un problème plus sérieux à mon avis.

Je me demande simplement, en présence de l'exception NotImplementedException, comment peut-on faire quoi que ce soit avec .Net ? Êtes-vous censé entourer chaque appel de méthode abstraite d'un bloc try catch pour vous prémunir contre les méthodes qui pourraient ne pas être implémentées ? Si vous attrapez une telle exception, que diable êtes-vous censé en faire ?

Je ne vois aucun moyen de tester si une méthode est réellement implémentée sans l'appeler. Puisque l'appeler peut avoir des effets secondaires, je ne peux pas faire toutes mes vérifications à l'avance et ensuite exécuter mon algorithme. Je dois exécuter mon algorithme, attraper les NotImplementedExceptions et, d'une manière ou d'une autre, ramener mon application à un état normal.

C'est fou. Fou. Insensé. Donc la question est : Pourquoi l'exception NotImplementedException existe-t-elle ? ?

En guise d'attaque préventive, je ne veux pas que quelqu'un réponde par "parce que les concepteurs doivent mettre cela dans le code généré automatiquement". C'est horrible. Je préférerais que le code auto-généré ne compile pas tant que vous ne fournissez pas une implémentation. Par exemple, l'implémentation générée automatiquement pourrait être "throw NotImplementedException ;" où NotImplementedException n'est pas défini !

Quelqu'un a-t-il déjà attrapé et traité une NotImplementedException ? Avez-vous déjà laissé une NotImplementedException dans votre code ? Si oui, cela représentait-il une bombe à retardement (c'est-à-dire que vous l'avez accidentellement laissée là) ou un défaut de conception (la méthode ne devrait pas être implémentée et ne sera jamais appelée) ?

Je me méfie beaucoup de l'exception NotSupportedException aussi... Non supporté ? Qu'est-ce que c'est ? Si elle n'est pas supportée, pourquoi fait-elle partie de votre interface ? Quelqu'un chez Microsoft peut-il épeler "improper inheritance" ? Mais je pourrais commencer une autre question pour cela si je n'obtiens pas trop d'abus pour celle-ci.

Informations supplémentaires :

Este est une lecture intéressante sur le sujet.

Il semble y avoir un fort accord avec Brad Abrams que l'exception "NotImplementedException" concerne une fonctionnalité qui n'est pas encore mise en œuvre, mais qui devrait vraiment l'être (et le sera). Quelque chose comme ce que vous pourriez commencer avec lorsque vous construisez une classe, récupérez toutes les méthodes qui lancent NotImplementedException, puis chassez-les avec du vrai code "

Commentaires de Jared Parsons sont très faibles et devraient probablement être ignorés : NotImplementedException : Lancez cette exception lorsqu'un type n'implémente pas une méthode pour toute autre raison.

En MSDN est encore plus faible sur le sujet, se contentant de déclarer que "l'exception qui est levée lorsqu'une méthode ou une opération demandée n'est pas implémentée".

142voto

R. Martinho Fernandes Points 96873

Il y a une situation où je le trouve utile : TDD.

J'écris mes tests, puis je crée des stubs pour que les tests compilent. Ces stubs ne font rien d'autre que throw new NotImplementedException(); . De cette façon, les tests échoueront par défaut, quoi qu'il arrive. Si j'utilisais une valeur de retour factice, cela pourrait générer des faux positifs. Maintenant que tous les tests compilent et échouent parce qu'il n'y a pas d'implémentation, je m'attaque aux stubs.

Comme je n'utilise jamais un NotImplementedException dans toute autre situation, aucun NotImplementedException ne passera jamais dans le code de sortie, puisqu'il fera toujours échouer certains tests.

Vous n'avez pas besoin de l'attraper partout. Les bonnes API documentent les exceptions levées. Ce sont celles-là que vous devez rechercher.

EDIT : J'ai écrit une règle FxCop pour les trouver.

Voici le code :

using System;
using Microsoft.FxCop.Sdk;

/// <summary>
/// An FxCop rule to ensure no <see cref="NotImplementedException"/> is
/// left behind on production code.
/// </summary>
internal class DoNotRaiseNotImplementedException : BaseIntrospectionRule
{
    private TypeNode _notImplementedException;
    private Member _currentMember;

    public DoNotRaiseNotImplementedException()
        : base("DoNotRaiseNotImplementedException",
               // The following string must be the assembly name (here
               // Bevonn.CodeAnalysis) followed by a dot and then the
               // metadata file name without the xml extension (here
               // DesignRules). See the note at the end for more details.
               "Bevonn.CodeAnalysis.DesignRules",
               typeof (DoNotRaiseNotImplementedException).Assembly) { }

    public override void BeforeAnalysis()
    {
        base.BeforeAnalysis();
        _notImplementedException = FrameworkAssemblies.Mscorlib.GetType(
            Identifier.For("System"),
            Identifier.For("NotImplementedException"));
    }

    public override ProblemCollection Check(Member member)
    {
        var method = member as Method;
        if (method != null)
        {
            _currentMember = member;
            VisitStatements(method.Body.Statements);
        }
        return Problems;
    }

    public override void VisitThrow(ThrowNode throwInstruction)
    {
        if (throwInstruction.Expression != null &&
            throwInstruction.Expression.Type.IsAssignableTo(_notImplementedException))
        {
            var problem = new Problem(
                GetResolution(),
                throwInstruction.SourceContext,
                _currentMember.Name.Name);
            Problems.Add(problem);
        }
    }
}

Et voici les métadonnées de la règle :

<?xml version="1.0" encoding="utf-8" ?>
<Rules FriendlyName="Bevonn Design Rules">
  <Rule TypeName="DoNotRaiseNotImplementedException" Category="Bevonn.Design" CheckId="BCA0001">
    <Name>Do not raise NotImplementedException</Name>
    <Description>NotImplementedException should not be used in production code.</Description>
    <Url>http://stackoverflow.com/questions/410719/notimplementedexception-are-they-kidding-me</Url>
    <Resolution>Implement the method or property accessor.</Resolution>
    <MessageLevel Certainty="100">CriticalError</MessageLevel>
    <Email></Email>
    <FixCategories>NonBreaking</FixCategories>
    <Owner></Owner>
  </Rule>
</Rules>

Pour le construire, vous devez :

  • référence Microsoft.FxCop.Sdk.dll y Microsoft.Cci.dll

  • Mettez les métadonnées dans un fichier appelé DesignRules.xml et l'ajouter en tant que ressource intégrée à votre assemblage

  • Nommez votre assemblée Bevonn.CodeAnalysis . Si vous souhaitez utiliser des noms différents pour les métadonnées ou les fichiers d'assemblage, veillez à modifier le deuxième paramètre du constructeur de base en conséquence.

Il suffit ensuite d'ajouter l'assemblage résultant à vos règles FxCop et de supprimer ces maudites exceptions de votre précieux code. Dans certains cas, il ne signalera pas une NotImplementedException lorsqu'elle est levée, mais je pense vraiment que vous êtes désespéré si vous écrivez un code aussi cthulhien. Pour les utilisations normales, c'est-à-dire throw new NotImplementedException(); mais il fonctionne, et c'est tout ce qui compte.

40voto

Scott Weinstein Points 11404

Il est là pour prendre en charge un cas d'utilisation assez commun, une API fonctionnelle mais seulement partiellement achevée. Imaginons que je souhaite que les développeurs testent et évaluent mon API WashDishes() fonctionne, du moins sur ma machine, mais je n'ai pas encore eu l'occasion d'encoder DryDishes() et encore moins PutAwayDishes() . Plutôt que d'échouer silencieusement ou d'afficher un message d'erreur énigmatique, je peux expliquer clairement la raison de cet échec. DryDishes() ne fonctionne pas - je ne l'ai pas encore mis en œuvre.

Son exception sœur NotSupportedException ont un sens surtout pour les modèles de fournisseurs. De nombreux lave-vaisselle ont une fonction de séchage, qui fait donc partie de l'interface, mais mon lave-vaisselle discount ne la prend pas en charge. Je peux le faire savoir via la fonction NotSupportedException

28voto

Mike Hofer Points 6559

Je vais résumer mon point de vue à ce sujet en un seul endroit, car il est éparpillé dans plusieurs commentaires :

  1. Vous utilisez NotImplementedException pour indiquer qu'un membre de l'interface n'est pas encore implémenté, mais le sera. Vous combinez cela avec des tests unitaires automatisés ou des tests d'assurance qualité pour identifier les fonctionnalités qui doivent encore être implémentées.

  2. Une fois la fonctionnalité mise en œuvre, vous supprimez le NotImplementedException . De nouveaux tests unitaires sont écrits pour la fonctionnalité afin de s'assurer qu'elle fonctionne correctement.

  3. NotSupportedException est généralement utilisé pour les fournisseurs qui ne prennent pas en charge des fonctionnalités qui n'ont pas de sens pour des types spécifiques. Dans ces cas, les types spécifiques lancent l'exception, les clients les attrapent et les traitent comme il se doit.

  4. La raison pour laquelle les deux NotImplementedException y NotSupportedException existent dans le Framework est simple : les situations qui y conduisent sont courantes, il est donc logique de les définir dans le Framework, afin que les développeurs n'aient pas à les redéfinir sans cesse. De plus, cela permet aux clients de savoir facilement quelle exception attraper (notamment dans le cadre d'un test unitaire). Si vous devez définir votre propre exception, ils doivent trouver quelle exception attraper, ce qui est à tout le moins une perte de temps contre-productive et souvent incorrecte.

19voto

aku Points 54867

Pourquoi l'exception NotImplementedException existe-t-elle ?

NotImplementedException est un excellent moyen de dire que quelque chose n'est pas encore prêt. La raison pour laquelle ce n'est pas prêt est une question distincte pour les auteurs de la méthode. Dans un code de production, il est peu probable que vous attrapiez cette exception, mais si c'est le cas, vous pouvez immédiatement voir ce qui s'est passé et c'est bien mieux que d'essayer de comprendre pourquoi les méthodes ont été appelées mais que rien ne s'est passé ou, pire encore, de recevoir un résultat "temporaire" et d'avoir des effets secondaires "bizarres".

I de l'exception Java UnsupportedOperationException de Java ?

Non, .NET a une NotSupportedException.

I NotImplementedExceptions et, d'une manière ou d'une autre, revenir en arrière dans mon algorithme. comment ramener mon application à un certain état sain

Une bonne API possède une documentation sur les méthodes XML qui décrit les exceptions possibles.

I NotSupportedException également... Pas supporté ? Quoi donc ? Si ce n'est pas supporté, pourquoi fait-il partie de votre interface ?

Il peut y avoir des millions de raisons. Par exemple, vous pouvez introduire une nouvelle version de l'API et ne pas vouloir/ne pas pouvoir supporter les anciennes méthodes. Encore une fois, il est préférable de voir l'exception descriptive plutôt que de creuser dans la documentation ou de déboguer du code tiers.

12voto

Mitch Wheat Points 169614

La principale utilisation d'une exception NotImplementedException est dans le code stub généré : de cette façon, vous n'oubliez pas de l'implémenter ! Par exemple, Visual Studio implémentera explicitement les méthodes/propriétés d'une interface avec le corps qui lancera une NotImplementedException.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X