Наследование комментариев для C# (на самом деле любой язык)

Допустим, у меня есть этот интерфейс

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

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

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

И этот класс

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

Есть ли способ или инструмент, который позволяет мне автоматически добавлять комментарии каждого члена в базовый класс или интерфейс?

Потому что я ненавижу переписывать одни и те же комментарии для каждого производного подкласса!

Я не только ненавижу это, но еще и трудно синхронизировать их.

Olivier Jacot-Descombes 04.08.2016 23:00
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
98
1
71 729
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Ответ принят как подходящий

GhostDoc делает именно это. Для методов, которые не унаследованы, он пытается создать описание на основе имени.

FlingThing() становится "Flings the Thing"

GhostDoc потрясающий, одна из тех вещей, которые я не знал, что мне нужно, но теперь не могу обойтись без: o)

NikolaiDante 05.12.2008 11:57

Автоматически сгенерированные документы мне кажутся очень плохой идеей. Они не добавляют никакой полезной информации, а только без надобности взрывают код. Если инструмент может понять, что делает метод, по его названию, то человек также может понять, и никакой документации не требуется.

Lensflare 08.01.2016 15:59

@Lensflare Это правда. Однажды мне пришлось использовать фреймворк, в котором были только такие сгенерированные комментарии, которые не добавляли никакой информации к методу / классу. Вместо «Этот метод делает то и то» комментарии вроде «Это метод XY класса Z». xD Также вы не могли просматривать код, поэтому он пошел методом проб и ошибок. Больше никогда! :-)

itmuckel 19.07.2016 13:49

@Lensflare Хотя я на 100% согласен с вами в том, что касается использования AGD как есть, я должен отметить, что AGD не предназначены для использования в качестве таких волшебных кнопок «сделать все». Вместо этого они предназначены для использования в качестве генераторов шаблонов, чтобы уменьшить количество шаблонной повторяющейся документации, которую вы должны написать самостоятельно, чтобы вы могли сосредоточиться на важных вещах. --- Например, он может создавать для вас разделы <summary>, <param>, <returns>, <throws>, etc.... Много раз с достаточно хорошими результатами; в других случаях требуются исправления или расширения, но все же сокращаются общие усилия.

XenoRo 29.09.2017 07:07

люди документация не для разработчиков, а для архитекторов, так что их задницы все прикрыты: «Эй, можно ли прочитать документацию по коду вашего проекта? Конечно, вот она».

Trident D'Gao 02.11.2017 19:32

Используйте /// <inheritdoc/>, если хотите наследование. Избегайте GhostDoc или чего-либо подобного.

Согласен, раздражает, что комментарии не передаются по наследству. Было бы довольно просто создать надстройку, если бы у кого-то было время (я бы хотел).

Тем не менее, в нашей базе кода мы помещаем XML-комментарии только к интерфейсам и добавляем дополнительные комментарии реализации к классу. Это работает для нас, поскольку наши классы являются частными / внутренними, и только интерфейс является общедоступным. Каждый раз, когда мы используем объекты через интерфейсы, у нас есть полные комментарии, отображаемые в интеллекте.

GhostDoc - хорошее начало, он упростил процесс написания комментариев. Особенно полезно поддерживать комментарии в актуальном состоянии, когда вы добавляете / удаляете параметры, повторно запускаете GhostDoc и он обновляет описание.

Я сбит с толку - вы сказали, что избегайте GhostDoc, но в конце вы, похоже, одобрили, что GhostDoc помогает упростить задачу. Вы можете пояснить, что имеете в виду?

Mike Marynowski 07.02.2020 07:22

Спасибо @MikeMarynowski. Это совет Старый. Думаю, в то время я хотел сказать, что GhostDoc, как и любой другой генератор, будет добавлять комментарии, но с почти бесполезными деталями, например. <param name = "origin">The origin.</param>. Дополнительные примеры см. В Призрачный Док говорит самые проклятые вещи. Visual Studio теперь имеет гораздо лучший линтинг и генераторы для xmldocs, чтобы вы знали, когда параметры + документы не совпадают, поэтому GhostDoc (или другие инструменты) больше не нужны.

Dennis 08.02.2020 09:29

Это есть в Java, и я постоянно им пользуюсь. Просто сделать:

/**
 * {@inheritDoc}
 */

И инструмент Javadoc это понимает.

В C# есть аналогичный маркер:

<inheritDoc/>

Вы можете прочитать больше здесь:

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

В C# нет маркера <inheritdoc/>: он есть в замок из песка. shfb.codeplex.com

Eric Dand 08.01.2015 00:39

Существует запрос голосовой функции пользователя на добавление <inheritdoc /> в C#. Поднимитесь и проголосуйте visualstudio.uservoice.com/forums/121579-visual-studio/…

deadlydog 09.01.2016 09:09

Ни C#, ни Java (или любой другой язык программирования) не имеют элементов «XML-документация». Это Комментарии. Составители ничего о них не знают. Все они строго используются сторонними генераторами документации, будь то javadoc, замок из песка или что-то еще.

James Curran 29.06.2017 16:10

Когда указывается Java или C#, это ОБЫЧНО означает сообщество связанных инструментов. Ни Java, ни C# не обладают большими возможностями в самом буквальном смысле. Было бы академическим аргументом утверждать, что Java или C# не могут подключаться к базе данных, потому что это делает библиотека времени выполнения.

JeffHeaton 12.07.2017 21:52

Visual Studio версии 16.4.0 и новее предоставляет intellisense для <inheritDoc />! docs.microsoft.com/en-us/visualstudio/releases/2019/…

ashbygeek 30.01.2020 00:27

У Resharper есть возможность копировать комментарии из базового класса или интерфейса.

Ой? Как? Я использую ReSharper и никогда не видел эту опцию при реализации или наследовании интерфейса ... Где это и как вы используете эту опцию?

Jazimov 21.10.2016 06:35

@Jazimov Когда вы нажимаете Alt + Enter на метод переопределения, появляется опция «Копировать документацию из базы».

svick 21.10.2016 15:01

Вы всегда можете использовать тег <inheritdoc />:

public class Foo : IFoo
{
    /// <inheritdoc />
    public void Foo() { ... }
    /// <inheritdoc />
    public void Bar() { ... }
    /// <inheritdoc />
    public void Snafu() { ... }
}

Используя атрибут cref, вы даже можете ссылаться на совершенно другой член в совершенно другом классе или пространстве имен!

public class Foo
{
    /// <inheritdoc cref = "System.String.IndexOf" />
    public void Bar() { ... } // this method will now have the documentation of System.String.IndexOf
}

Я не знал, что <inheritdoc /> вообще существует ... Но, насколько я понимаю, комментарий для этого метода не отображается с помощью intellisense.

gerleim 07.10.2014 16:57

@gerleim Посмотрите ответ Джеффа Хитона годом ранее и комментарий под ним. В Sandcastle есть <inheritdoc />, а не C#.

rbwhitaker 14.01.2015 22:42

Я вижу комментарии из интерфейса в intellisense с помощью inheritdoc, а также, если в производном классе вообще нет документации с кодом. Но это могло быть из-за того, что я стал резче.

Tim Abell 03.01.2017 16:50

В Rider я также вижу комментарии из интерфейса в intellisense с inheritdoc, а также, если там нет code-doc.

Horcrux7 04.07.2017 09:37

В Resharper 2017.2 улучшена поддержка inheritdoc jetbrains.com/resharper/whatsnew

Dav Evans 01.09.2017 05:05

VS2017 Professional показывает мне унаследованные комментарии.

Douglas Gaskell 06.02.2018 05:05

Visual Studio Enterprise 2017 (версия 15.9.3) не отображает унаследованные комментарии.

herzbube 20.12.2018 10:59

Это странно, но я вижу комментарии из интерфейса даже без inheridoc. (VS Enterprise 2017 15.7.6)

Reven 13.02.2019 14:51

Visual Studio версии 16.4.0 и новее предоставляет intellisense для этой нотации! docs.microsoft.com/en-us/visualstudio/releases/2019/…

ashbygeek 30.01.2020 00:26

Другой способ - использовать тег документации <see /> XML. Это требует дополнительных усилий, но работает из коробки ...

Вот некоторые примеры:

/// <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() { ... }
}

Обновлять:

Теперь я предпочитаю использовать /// <inheritdoc/>, который теперь поддерживается ReSharper.

В итоге я создал инструмент для пост-обработки файлов XML-документации, чтобы добавить поддержку замены тега <inheritdoc/> в самих файлах XML-документации. Доступно по адресу www.inheritdoc.io (доступна бесплатная версия).

Я бы сказал, чтобы напрямую использовать

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

И

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

Вы должны поместить эти комментарии только в предыдущую строку вашего класса / метода.

Это позволит получить информацию о ваших комментариях, например, из интерфейса, который вы задокументировали, например:

    /// <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);

Спасибо за совет! Такой подход более явный и решает проблему наследования описания класса от класса объекта (даже при реализации интерфейса).

Denis Babarykin 11.03.2020 15:35

Что ж, есть какое-то родное решение, которое я нашел для .NET Core 2.2.

Идея состоит в том, чтобы использовать тег <include>.

Вы можете добавить <GenerateDocumentationFile>true</GenerateDocumentationFile> в ваш .csproj файл.

У вас может быть интерфейс:

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

И кое-что, что от него унаследовано:

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.");
    }
}

Хорошо, это немного страшно, но это добавляет ожидаемые элементы в YourNamespace.xml.

Если вы создаете конфигурацию Debug, вы можете заменить Release на Debug в атрибуте file тега include.

Чтобы найти правильный membername для ссылки, просто откройте сгенерированный файл Documentation.xml.

Я также предполагаю, что этот подход требует, чтобы проект или решение создавалось как минимум дважды (первый раз для создания исходного XML-файла, а второй раз для копирования элементов из него в себя).

Яркая сторона заключается в том, что Visual Studio проверяет скопированные элементы, поэтому намного проще синхронизировать документацию и код с интерфейсом / базовым классом и т. д. (Например, имена аргументов, имена параметров типа и т. д.).

В моем проекте я получил как <inheritdoc/> (для DocFX), так и <include/> (для публикации пакетов NuGet и для проверки в 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();

Другие вопросы по теме