223

在编写 xml 文档时,您可以使用<see cref="something">something</see>,当然可以。但是如何引用具有泛型类型的类或方法呢?

public class FancyClass<T>
{
  public string FancyMethod<K>(T value) { return "something fancy"; }
}

如果我要在某处编写 xml 文档,我将如何引用花哨的类?我怎样才能引用一个FancyClass<string>?方法呢?

例如,在另一个类中,我想让用户知道我将返回一个FancyClass<int>. 我怎么能为此做一个see cref的事情?

4

8 回答 8

288

要引用该方法:

/// <see cref="FancyClass{T}.FancyMethod{K}(T)"/> for more information.
于 2009-02-10T13:01:18.713 回答
48

TL;博士:

“我将如何参考FancyClass<T>?”

   /// <see cref="FancyClass{T}"/>

“怎么样FancyClass<T>.FancyMethod<K>(T value)?”

   /// <see cref="FancyClass{T}.FancyMethod{K}(T)"/>

“我怎样才能引用一个FancyClass<string>?”

   /// <see cref="SomeType.SomeMethod(FancyClass{string})"/>
   /// <see cref="FancyClass{T}"/> whose generic type argument is <see cref="string"/>

虽然您可以引用其签名包含的方法FancyClass<string>(例如作为参数类型),但您不能直接引用这种封闭的泛型类型。第二个示例解决了该限制。(这可以在静态方法的MSDN 参考页面System.String.Concat(IEnumerable<string>)上看到)。:

XML 文档注释cref规则:

  • 用大括号{}而不是<>尖括号包围泛型类型参数列表。这使您免于逃避后者,&lt;并且&gt;— 请记住,文档注释是 XML!

  • 如果包含前缀(例如T:类型、M:方法、P:属性、F:字段),编译器不会对引用执行任何验证,而只是将cref属性值直接复制到文档 XML 输出。出于这个原因,您必须使用适用于此类文件的特殊“ID 字符串”语法:始终使用完全限定的标识符,并使用反引号来引用泛型类型参数(`n在类型上,``n在方法上)。

  • 如果省略前缀,则适用常规语言命名规则:您可以删除存在using语句的命名空间,并且可以使用语言的类型关键字,例如int代替System.Int32. 此外,编译器将检查引用的正确性。

XML 文档注释cref备忘单:

namespace X
{
    using System;

    /// <see cref="I1"/>  (or <see cref="X.I1"/> from outside X)
    /// <see cref="T:X.I1"/>
    interface I1
    {
        /// <see cref="I1.M1(int)"/>  (or <see cref="M1(int)"/> from inside I1)
        /// <see cref="M:X.I1.M1(System.Int32)"/>
        void M1(int p);

        /// <see cref="I1.M2{U}(U)"/>
        /// <see cref="M:X.I1.M2``1(``0)"/>
        void M2<U>(U p);

        /// <see cref="I1.M3(Action{string})"/>
        /// <see cref="M:X.I1.M3(System.Action{System.String})"/>
        void M3(Action<string> p);
    }

    /// <see cref="I2{T}"/>
    /// <see cref="T:X.I2`1"/>
    interface I2<T>
    {
        /// <see cref="I2{T}.M1(int)"/>
        /// <see cref="M:X.I2`1.M1(System.Int32)"/>
        void M1(int p);

        /// <see cref="I2{T}.M2(T)"/>
        /// <see cref="M:X.I2`1.M2(`0)"/>
        void M2(T p);

        /// <see cref="I2{T}.M3{U}(U)"/>
        /// <see cref="M:X.I2`1.M3``1(``0)"/>
        void M3<U>(U p);
    }
}
于 2016-12-18T12:07:17.063 回答
47
/// <summary>Uses a <see cref="FancyClass{T}" /> instance.</summary>

顺便说一句,它出现在.Net Framework 2.03.0的 MSDN 文档中,但在3.5 版本中消失了

于 2009-02-10T12:53:39.980 回答
24

到目前为止,没有一个答案完全适合我。除非完全解析,否则ReSharper 不会将 see 标记转换为Ctrl+click-able 链接(例如)。图片在这里

如果 OP 中的方法位于名为 的命名空间中Test,则显示的方法的完全解析链接将是:

<see cref="M:Test.FancyClass`1.FancyMethod``1(`0)"/>

正如您可能能够解决的那样,在类类型参数的数量之前应该只有一个反引号,然后在方法类型参数的数量之前有两个反引号,然后参数是具有适当数量的反引号的零索引参数。

所以我们可以看到FancyClass有一个类类型参数,FancyMethod有一个类型参数,一个FancyClass参数类型的对象会被传递给方法。

正如您在此示例中更清楚地看到的那样:

namespace Test
{
    public class FancyClass<A, B>
    {
        public void FancyMethod<C, D, E>(A a, B b, C c, D d, E e) { }
    }
}

链接变为:

M:Test.FancyClass`2.FancyMethod``3(`0,`1,``0,``1,``2)

或“具有两个类型参数的类,该类具有具有三个类型参数的方法,其中方法参数为ClassType1, ClassType2, MethodType1, MethodType2, MethodType3


作为补充说明,我没有在任何地方找到这个文档,而且我不是天才,编译器告诉了我这一切。您所要做的就是创建一个测试项目,启用 XML 文档,然后插入您想要为其计算链接的代码,并在其上放置一个 XML 文档注释的开头(///):

namespace Test
{
    public class FancyClass<T>
    {
        ///
        public string FancyMethod<K>(T value) { return "something fancy"; }
    }

    public class Test
    {
        public static void Main(string[] args) { }
    }
}

然后构建您的项目,输出的 XML 文档在属性下的doc-> members->member元素中包含链接name

<?xml version="1.0"?>
<doc>
    <assembly>
        <name>Test</name>
    </assembly>
    <members>
        <member name="M:Test.FancyClass`1.FancyMethod``1(`0)">

        </member>
    </members>
</doc>
于 2015-12-10T17:37:04.513 回答
10

进一步来自 Lasse 和 TBC 的回答:

/// <see cref="T:FancyClass`1{T}"/> for more information.

/// <see cref="M:FancyClass`1{T}.FancyMethod`1{K}(T)"/> for more information.

还将正确提供工具提示,而他们的版本使用花括号来呈现它。

于 2011-10-26T11:48:07.887 回答
7
/// Here we discuss the use of <typeparamref name="TYourExcellentType"/>.
/// <typeparam name="TYourExcellentType">Your exellent documentation</typeparam>
于 2016-11-10T15:54:16.620 回答
1
/// <see cref="FancyClass&lt;T>.FancyMethod&lt;K>(T)"/> for more information.
于 2012-01-28T15:25:26.110 回答
1

这是我在其他地方给出的答案。它也适用于类和方法。

我尝试了堆栈溢出的所有内容,以获得适用于多种情况的结果。这是一个适合我的解决方案。(这对其他人来说是主观的。)

  1. 产生可点击的链接。
  2. 将鼠标悬停在标识符上有效。
  3. 正确生成 .xml 文件。
  4. 在智能感知中不会产生错误。
  5. 适用于可为空的泛型类型参数。
  6. 在 Resharper 中工作,它是内置的 XML Doc 窗口(Resharper -> 编辑 -> 显示快速文档)
  7. 适用于 Atomineer Pro Documentaion Visual Studio Extension 的 XAM Doc Preview。
  8. 适用于泛型类型的泛型类型。

示例 #1

  /// <summary>
  ///  This instance field holds a reference to the
  ///  <see cref="ConcurrentDictionary{Decimal, Boolean}"/> as
  ///  <see cref="T:ConcurrentDictionary&lt;decimal, bool?&gt;"/> that contains
  ///  the list of all PDF's that are currently opened and being displayed.
  /// </summary>
  private ConcurrentDictionary<decimal, bool?> openedPdfs = default!;

  Note: 
    The ConcurrentDictionary{Decimal, Boolean} will correctly produce a
    clickable link of ConcurrentDictionary{TKey, TValue} on hovering while
    T:ConcurrentDictionary&lt;decimal, bool?&gt; makes sure the reader gets
    information on what type TKey and TValue are.

示例#2(使用“T”)

  /// <summary>
  ///  This instance field holds a reference to the
  ///  <see cref="ConcurrentDictionary{TKey, TValue}"/> as
  ///  <see cref="T:ConcurrentDictionary&lt;decimal, bool?&gt;"/> that contains
  ///  the list of all PDF's that are currently opened and being displayed.
  /// </summary>
  private ConcurrentDictionary<decimal, bool?> openedPdfs = default!;
于 2021-03-12T22:18:31.593 回答