113

假设我有这个界面

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

有没有办法,或者有没有工具可以让我自动将每个成员的注释放入基类或接口中?

因为我讨厌为每个派生子类重写相同的注释!

4

9 回答 9

188

您始终可以使用<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
}
于 2011-09-27T15:22:10.613 回答
29

/// <inheritdoc/>如果您想要继承,请使用。避免使用 GhostDoc 或类似的东西。

我同意评论没有被继承是很烦人的。如果有人有时间(我希望我这样做),这将是一个相当简单的插件。

也就是说,在我们的代码库中,我们只在接口上放置 XML 注释,并向类添加额外的实现注释。这对我们有用,因为我们的类是私有/内部的,只有接口是公共的。每当我们通过接口使用对象时,我们都会在智能中显示完整的评论。

GhostDoc 是一个好的开始,它使编写评论的过程更容易。当您添加/删除参数、重新运行 GhostDoc 并且它将更新描述时,保持评论最新特别有用。

于 2008-12-05T06:48:25.077 回答
18

GhostDoc正是这样做的。对于未继承的方法,它会尝试根据名称创建描述。

FlingThing() 变成"Flings the Thing"

于 2008-12-05T05:15:00.413 回答
14

Java 有这个,我一直在使用它。做就是了:

/**
 * {@inheritDoc}
 */

Javadoc 工具可以解决这个问题。

C# 有类似的标记:

<inheritDoc/>

你可以在这里阅读更多:

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

于 2010-10-11T22:43:58.283 回答
14

我会说直接使用

/// <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);
于 2018-09-19T06:33:49.063 回答
9

ReSharper 可以选择从基类或接口复制注释。

于 2011-04-21T17:16:32.137 回答
9

另一种方法是使用<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 现在支持的。

于 2017-01-30T13:56:20.277 回答
1

我最终创建了一个工具来对 XML 文档文件进行后处理,以添加对替换<inheritdoc/>XML 文档文件本身中的标记的支持。可在www.inheritdoc.io 获得(提供免费版本)。

于 2017-12-20T06:23:45.013 回答
0

嗯,有一种原生解决方案,我为 .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.

如果您构建配置,您可以在标签的属性中进行交换DebugReleaseDebugfileinclude

要找到正确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();
于 2019-08-12T20:36:42.953 回答