Допустим, у меня есть этот интерфейс
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() { ... }
}
Есть ли способ или инструмент, который позволяет мне автоматически добавлять комментарии каждого члена в базовый класс или интерфейс?
Потому что я ненавижу переписывать одни и те же комментарии для каждого производного подкласса!





GhostDoc делает именно это. Для методов, которые не унаследованы, он пытается создать описание на основе имени.
FlingThing() становится "Flings the Thing"
GhostDoc потрясающий, одна из тех вещей, которые я не знал, что мне нужно, но теперь не могу обойтись без: o)
Автоматически сгенерированные документы мне кажутся очень плохой идеей. Они не добавляют никакой полезной информации, а только без надобности взрывают код. Если инструмент может понять, что делает метод, по его названию, то человек также может понять, и никакой документации не требуется.
@Lensflare Это правда. Однажды мне пришлось использовать фреймворк, в котором были только такие сгенерированные комментарии, которые не добавляли никакой информации к методу / классу. Вместо «Этот метод делает то и то» комментарии вроде «Это метод XY класса Z». xD Также вы не могли просматривать код, поэтому он пошел методом проб и ошибок. Больше никогда! :-)
@Lensflare Хотя я на 100% согласен с вами в том, что касается использования AGD как есть, я должен отметить, что AGD не предназначены для использования в качестве таких волшебных кнопок «сделать все». Вместо этого они предназначены для использования в качестве генераторов шаблонов, чтобы уменьшить количество шаблонной повторяющейся документации, которую вы должны написать самостоятельно, чтобы вы могли сосредоточиться на важных вещах. --- Например, он может создавать для вас разделы <summary>, <param>, <returns>, <throws>, etc.... Много раз с достаточно хорошими результатами; в других случаях требуются исправления или расширения, но все же сокращаются общие усилия.
люди документация не для разработчиков, а для архитекторов, так что их задницы все прикрыты: «Эй, можно ли прочитать документацию по коду вашего проекта? Конечно, вот она».
Используйте /// <inheritdoc/>, если хотите наследование. Избегайте GhostDoc или чего-либо подобного.
Согласен, раздражает, что комментарии не передаются по наследству. Было бы довольно просто создать надстройку, если бы у кого-то было время (я бы хотел).
Тем не менее, в нашей базе кода мы помещаем XML-комментарии только к интерфейсам и добавляем дополнительные комментарии реализации к классу. Это работает для нас, поскольку наши классы являются частными / внутренними, и только интерфейс является общедоступным. Каждый раз, когда мы используем объекты через интерфейсы, у нас есть полные комментарии, отображаемые в интеллекте.
GhostDoc - хорошее начало, он упростил процесс написания комментариев. Особенно полезно поддерживать комментарии в актуальном состоянии, когда вы добавляете / удаляете параметры, повторно запускаете GhostDoc и он обновляет описание.
Я сбит с толку - вы сказали, что избегайте GhostDoc, но в конце вы, похоже, одобрили, что GhostDoc помогает упростить задачу. Вы можете пояснить, что имеете в виду?
Спасибо @MikeMarynowski. Это совет Старый. Думаю, в то время я хотел сказать, что GhostDoc, как и любой другой генератор, будет добавлять комментарии, но с почти бесполезными деталями, например. <param name = "origin">The origin.</param>. Дополнительные примеры см. В Призрачный Док говорит самые проклятые вещи. Visual Studio теперь имеет гораздо лучший линтинг и генераторы для xmldocs, чтобы вы знали, когда параметры + документы не совпадают, поэтому GhostDoc (или другие инструменты) больше не нужны.
Это есть в Java, и я постоянно им пользуюсь. Просто сделать:
/**
* {@inheritDoc}
*/
И инструмент Javadoc это понимает.
В C# есть аналогичный маркер:
<inheritDoc/>
Вы можете прочитать больше здесь:
http://www.ewoodruff.us/shfbdocs/html/79897974-ffc9-4b84-91a5-e50c66a0221d.htm
В C# нет маркера <inheritdoc/>: он есть в замок из песка. shfb.codeplex.com
Существует запрос голосовой функции пользователя на добавление <inheritdoc /> в C#. Поднимитесь и проголосуйте visualstudio.uservoice.com/forums/121579-visual-studio/…
Ни C#, ни Java (или любой другой язык программирования) не имеют элементов «XML-документация». Это Комментарии. Составители ничего о них не знают. Все они строго используются сторонними генераторами документации, будь то javadoc, замок из песка или что-то еще.
Когда указывается Java или C#, это ОБЫЧНО означает сообщество связанных инструментов. Ни Java, ни C# не обладают большими возможностями в самом буквальном смысле. Было бы академическим аргументом утверждать, что Java или C# не могут подключаться к базе данных, потому что это делает библиотека времени выполнения.
Visual Studio версии 16.4.0 и новее предоставляет intellisense для <inheritDoc />! docs.microsoft.com/en-us/visualstudio/releases/2019/…
У Resharper есть возможность копировать комментарии из базового класса или интерфейса.
Ой? Как? Я использую ReSharper и никогда не видел эту опцию при реализации или наследовании интерфейса ... Где это и как вы используете эту опцию?
@Jazimov Когда вы нажимаете Alt + Enter на метод переопределения, появляется опция «Копировать документацию из базы».
Вы всегда можете использовать тег <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 Посмотрите ответ Джеффа Хитона годом ранее и комментарий под ним. В Sandcastle есть <inheritdoc />, а не C#.
Я вижу комментарии из интерфейса в intellisense с помощью inheritdoc, а также, если в производном классе вообще нет документации с кодом. Но это могло быть из-за того, что я стал резче.
В Rider я также вижу комментарии из интерфейса в intellisense с inheritdoc, а также, если там нет code-doc.
В Resharper 2017.2 улучшена поддержка inheritdoc jetbrains.com/resharper/whatsnew
VS2017 Professional показывает мне унаследованные комментарии.
Visual Studio Enterprise 2017 (версия 15.9.3) не отображает унаследованные комментарии.
Это странно, но я вижу комментарии из интерфейса даже без inheridoc. (VS Enterprise 2017 15.7.6)
Visual Studio версии 16.4.0 и новее предоставляет intellisense для этой нотации! docs.microsoft.com/en-us/visualstudio/releases/2019/…
Другой способ - использовать тег документации <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);
Спасибо за совет! Такой подход более явный и решает проблему наследования описания класса от класса объекта (даже при реализации интерфейса).
Что ж, есть какое-то родное решение, которое я нашел для .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();
Я не только ненавижу это, но еще и трудно синхронизировать их.