Héritage de commentaire pour C # (en fait n'importe quel langage)

93

Supposons que j'ai cette interface

public interface IFoo
{
    ///<summary>
    /// Foo method
    ///</summary>
    void Foo();

    ///<summary>
    /// Bar method
    ///</summary>
    void Bar();

    ///<summary>
    /// Situation normal
    ///</summary>
    void Snafu();
}

Et cette classe

public class Foo : IFoo
{
    public void Foo() { ... }
    public void Bar() { ... }
    public void Snafu() { ... }
}

Y a-t-il un moyen, ou existe-t-il un outil qui me permet de mettre automatiquement les commentaires de chaque membre dans une classe ou une interface de base?

Parce que je déteste réécrire les mêmes commentaires pour chaque sous-classe dérivée!

jumpinjackie
la source
14
Non seulement je déteste ça, mais il est également difficile de les synchroniser.
Olivier Jacot-Descombes

Réponses:

17

GhostDoc fait exactement cela. Pour les méthodes qui ne sont pas héritées, il essaie de créer une description à partir du nom.

FlingThing() devient "Flings the Thing"

James Curran
la source
2
GhostDoc est génial, une de ces choses dont je ne savais pas avoir besoin mais que je ne peux plus me passer: o)
NikolaiDante
179
Les documents générés automatiquement me semblent une très mauvaise idée. Ils n'ajoutent aucune information utile mais font exploser le code inutilement. Si un outil peut comprendre ce qu'une méthode fait à partir de son nom, alors une personne peut également comprendre et aucun document n'est nécessaire.
Lensflare
8
@Lensflare C'est tellement vrai. Une fois, j'ai dû utiliser un cadre qui n'avait que de tels commentaires générés, qui n'ajoutait AUCUNE information à la méthode / classe. Au lieu de "Cette méthode fait ceci et cela", les commentaires étaient comme "Ceci est la méthode XY de classe Z". xD De plus, vous ne pouvez pas parcourir le code, il est donc passé par essais et erreurs. Plus jamais! :-)
itmuckel
15
@Lensflare Bien que je sois à 100% d'accord avec vous pour ce qui est de me fier aux AGD tels quels , je dois souligner que les AGD ne sont pas destinés à être utilisés comme des boutons magiques «tout faire» comme ça. Au lieu de cela, ils sont destinés à être utilisés comme générateurs de modèles pour réduire la quantité de documentation standard et répétitive que vous devez écrire vous-même, afin que vous puissiez vous concentrer sur les choses importantes. --- Par exemple, il peut générer les <summary>, <param>, <returns>, <throws>, etc...sections pour vous. Plusieurs fois avec des résultats assez bons; d'autres fois nécessitant des corrections ou une expansion, mais réduisant encore l'effort global.
XenoRo
5
les gens, la documentation n'est pas pour les développeurs, c'est pour les architectes donc leurs mégots sont tous couverts: "Hé, pouvons-nous lire la documentation du code de votre projet? Bien sûr, la voici."
Trident D'Gao
151

Vous pouvez toujours utiliser <inheritdoc />tag.

public class Foo : IFoo
{
    /// <inheritdoc />
    public void Foo() { ... }
    /// <inheritdoc />
    public void Bar() { ... }
    /// <inheritdoc />
    public void Snafu() { ... }
}
Vadim
la source
7
Je ne savais même pas que <inheritdoc /> existait ... Mais pour autant que je sache, le commentaire de cette méthode n'apparaît pas avec intellisense.
gerleim
12
@gerleim Regardez la réponse de Jeff Heaton d'un an plus tôt, et le commentaire en dessous. Sandcastle a <inheritdoc />, pas C #.
rbwhitaker
4
Je vois des commentaires de l'interface dans intellisense avec inheritdoc, et aussi s'il n'y a pas de code-doc du tout sur la classe dérivée. Mais cela pourrait être parce que j'ai un resharper.
Tim Abell
9
Resharper 2017.2 a amélioré la prise en charge de inheritdoc jetbrains.com/resharper/whatsnew
Dav Evans
3
Visual Studio Enterprise 2017 (version 15.9.3) n'affiche pas les commentaires hérités pour moi.
herzbube
26

À utiliser /// <inheritdoc/>si vous voulez l'héritage. Évitez GhostDoc ou quelque chose comme ça.

Je conviens qu'il est ennuyeux que les commentaires ne soient pas hérités. Ce serait un complément assez simple à créer si quelqu'un avait le temps (j'aurais aimé le faire).

Cela dit, dans notre base de code, nous mettons des commentaires XML sur les interfaces uniquement et ajoutons des commentaires d'implémentation supplémentaires à la classe. Cela fonctionne pour nous car nos classes sont privées / internes et seule l'interface est publique. Chaque fois que nous utilisons les objets via les interfaces, nous avons des commentaires complets affichés dans l'intellisence.

GhostDoc est un bon début et a facilité le processus d'écriture des commentaires. Il est particulièrement utile de garder les commentaires à jour lorsque vous ajoutez / supprimez des paramètres, réexécutez GhostDoc et il mettra à jour la description.

Dennis
la source
Je suis confus - vous avez dit d'éviter GhostDoc, mais à la fin, vous avez apparemment approuvé GhostDoc pour faciliter les choses. Pouvez-vous clarifier ce que vous voulez dire?
Mike Marynowski
Merci @MikeMarynowski. C'est un vieux conseil. Je pense que je voulais dire à l'époque que GhostDoc, comme tout autre générateur, ajoutera des commentaires mais avec des détails presque inutiles par exemple <param name="origin">The origin.</param>. Voir ghostdoc dit les choses les plus damnées pour plus d'exemples. Visual Studio a maintenant de bien meilleurs linting et générateurs pour xmldocs pour vous faire savoir quand les paramètres + les documents ne sont pas alignés, donc GhostDoc (ou d'autres outils) ne sont plus nécessaires.
Dennis
15

Java a ceci, et je l'utilise tout le temps. Faites simplement:

/**
 * {@inheritDoc}
 */

Et l'outil Javadoc le comprend.

C # a un marqueur similaire:

<inheritDoc/>

Vous pouvez lire plus ici:

http://www.ewoodruff.us/shfbdocs/html/79897974-ffc9-4b84-91a5-e50c66a0221d.htm

JeffHeaton
la source
37
C # n'a pas le <inheritdoc/>marqueur: Sandcastle l' a. shfb.codeplex.com
Eric Dand
8
Il existe une demande de fonctionnalité vocale utilisateur pour ajouter <inheritdoc /> à C #. Votez-le sur visualstudio.uservoice.com/forums/121579-visual-studio
...
1
Ni C # ni Java (ni aucun autre langage de programmation) n'ont aucun des éléments "XML doc". Ce sont des commentaires . Les compilateurs n'en savent rien. Ils sont tous strictement utilisés par les générateurs de documentation tiers, que ce soit javadoc ou sandcastle ou autre.
James Curran
4
Lorsque Java ou C # est indiqué, cela signifie généralement la communauté des outils associés. Ni Java ni C # n'ont beaucoup de capacités au sens très littéral. Ce serait un argument académique d'affirmer que Java ou C # n'ont pas la capacité de se connecter à une base de données, car la bibliothèque d'exécution le fait.
JeffHeaton
2
Visual Studio version 16.4.0 et plus récente fournissent intellisense pour <inheritDoc />! docs.microsoft.com/en-us/visualstudio/releases/2019/…
ashbygeek
10

Je dirais d'utiliser directement le

/// <inheritdoc cref="YourClass.YourMethod"/>  --> For methods inheritance

Et

/// <inheritdoc cref="YourClass"/>  --> For directly class inheritance

Vous devez mettre ces commentaires juste sur la ligne précédente de votre classe / méthode

Cela obtiendra les informations de vos commentaires par exemple à partir d'une interface que vous avez documentée comme:

    /// <summary>
    /// This method is awesome!
    /// </summary>
    /// <param name="awesomeParam">The awesome parameter of the month!.</param>
    /// <returns>A <see cref="AwesomeObject"/> that is also awesome...</returns>
    AwesomeObject CreateAwesome(WhateverObject awesomeParam);
Gatsby
la source
Merci du conseil! Cette approche est plus explicite et résout le problème de la description de classe d'héritage à partir de la classe d'objet (même lors de l'implémentation de l'interface).
Denis Babarykin
8

Resharper a une option pour copier les commentaires de la classe de base ou de l'interface.

svick
la source
1
Oh? Comment? J'utilise ReSharper et je n'ai jamais vu cette option lors de l'implémentation ou de l'héritage d'une interface ... Où est-elle et comment utiliser cette option?
Jazimov
2
@Jazimov Lorsque vous Alt + Entrez la méthode de remplacement, il y a une option pour "Copier la documentation de la base".
svick
8

Une autre façon consiste à utiliser la <see />balise de documentation XML. Ceci est un effort supplémentaire mais fonctionne hors de la boîte ...

Voici quelques exemples:

/// <summary>
/// Implementation of <see cref="IFoo"/>.
/// </summary>
public class Foo : IFoo
{
    /// <summary>
    /// See <see cref="IFoo"/>.
    /// </summary>
    public void Foo() { ... }

    /// <summary>
    /// See <see cref="IFoo.Bar"/>
    /// </summary>
    public void Bar() { ... }

    /// <summary>
    /// This implementation of <see cref="IFoo.Snafu"/> uses the a caching algorithm for performance optimization.
    /// </summary>
    public void Snafu() { ... }
}

Mettre à jour:

Je préfère maintenant utiliser /// <inheritdoc/>ce qui est maintenant pris en charge par ReSharper.

Mathias Rotter
la source
1

J'ai fini par créer un outil pour post-traiter les fichiers de documentation XML afin d'ajouter la prise en charge du remplacement de la <inheritdoc/>balise dans les fichiers de documentation XML eux-mêmes. Disponible sur www.inheritdoc.io (version gratuite disponible).

K Johnson
la source
0

Eh bien, il existe une sorte de solution native, que j'ai trouvée pour .NET Core 2.2

L'idée est d'utiliser <include> tag.

Vous pouvez ajouter <GenerateDocumentationFile>true</GenerateDocumentationFile>votre.csproj fichier.

Vous pourriez avoir une interface:

namespace YourNamespace
{
    /// <summary>
    /// Represents interface for a type.
    /// </summary>
    public interface IType
    {
        /// <summary>
        /// Executes an action in read access mode.
        /// </summary>
        void ExecuteAction();
    }
}

Et quelque chose qui en hérite:

using System;

namespace YourNamespace
{
    /// <summary>
    /// A type inherited from <see cref="IType"/> interface.
    /// </summary>
    public class InheritedType : IType
    {
        /// <include file='bin\Release\netstandard2.0\YourNamespace.xml' path='doc/members/member[@name="M:YourNamespace.IType.ExecuteAction()"]/*'/>
        public void ExecuteAction() => Console.WriteLine("Action is executed.");
    }
}

Ok, c'est un peu effrayant, mais cela ajoute les éléments attendus au fichier YourNamespace.xml.

Si vous créez une Debugconfiguration, vous pouvez échanger Releasepour Debugl' fileattribut de includebalise.

Pour trouver une référence correcte member, nameouvrez simplement le Documentation.xmlfichier généré .

Je suppose également que cette approche nécessite qu'un projet ou une solution soit construit au moins deux fois (la première fois pour créer un fichier XML initial et la deuxième fois pour en copier des éléments sur lui-même).

Le bon côté est que Visual Studio valide les éléments copiés, il est donc beaucoup plus facile de synchroniser la documentation et le code avec l'interface / la classe de base, etc. (par exemple les noms d'arguments, les noms de paramètres de type, etc.).

À mon projet, j'ai fini avec <inheritdoc/>(pour DocFX) et <include/>(pour la publication de packages NuGet et pour la validation chez Visual Studio):

        /// <inheritdoc />
        /// <include file='bin\Release\netstandard2.0\Platform.Threading.xml' path='doc/members/member[@name="M:Platform.Threading.Synchronization.ISynchronization.ExecuteReadOperation(System.Action)"]/*'/>
        public void ExecuteReadOperation(Action action) => action();
Konard
la source