[英]How to reference generic classes and methods in xml documentation
在编写 xml 文档时,您可以使用<see cref="something">something</see>
,这当然有效。 但是如何引用具有泛型类型的类或方法呢?
public class FancyClass<T>
{
public string FancyMethod<K>(T value) { return "something fancy"; }
}
如果我要在某处编写 xml 文档,我将如何引用这个花哨的类? 我如何引用FancyClass<string>
? 方法呢?
例如,在另一个类中,我想让用户知道我将返回FancyClass<int>
一个实例。 我怎么能为此做一个查看 cref 的东西?
要引用该方法:
/// <see cref="FancyClass{T}.FancyMethod{K}(T)"/> for more information.
/// <summary>Uses a <see cref="FancyClass{T}" /> instance.</summary>
顺便说一句,它出现在.Net Framework 2.0和3.0的 MSDN 文档中,但它在3.5 版中消失了
“我将如何引用
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>
(例如,作为参数类型),则不能引用这样的直接关闭通用类型。 第二个示例解决了该限制。 (这可以在静态System.String.Concat(IEnumerable<string>)
方法的MSDN 参考页面上看到)。 :
cref
规则: 用大括号{}
而不是<>
尖括号将泛型类型参数列表括起来。 这使您免于将后者转义为<
和>
— 请记住,文档注释是 XML!
如果包含前缀(例如T:
表示类型, M:
表示方法, P:
表示属性, F:
表示字段),编译器不会对引用执行任何验证,而只是将cref
属性值直接复制到文档 XML 输出。 因此,您必须使用适用于此类文件的特殊“ID 字符串”语法:始终使用完全限定的标识符,并使用反引号引用泛型类型参数( `n
在类型上, ``n
在方法上) .
如果省略 prefix ,则适用常规语言命名规则:您可以删除有using
语句的命名空间,并且可以使用语言的类型关键字,例如int
而不是System.Int32
。 此外,编译器将检查引用的正确性。
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);
}
}
到目前为止显示的答案都没有完全适合我。 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 文档在属性name
下的doc
-> members
-> member
元素中包含链接:
<?xml version="1.0"?>
<doc>
<assembly>
<name>Test</name>
</assembly>
<members>
<member name="M:Test.FancyClass`1.FancyMethod``1(`0)">
</member>
</members>
</doc>
进一步来自 Lasse 和 TBC 的回答:
/// <see cref="T:FancyClass`1{T}"/> for more information.
/// <see cref="M:FancyClass`1{T}.FancyMethod`1{K}(T)"/> for more information.
还将正确提供工具提示,而他们的版本则使用花括号呈现它。
/// Here we discuss the use of <typeparamref name="TYourExcellentType"/>.
/// <typeparam name="TYourExcellentType">Your exellent documentation</typeparam>
/// <see cref="FancyClass<T>.FancyMethod<K>(T)"/> for more information.
这是我在别处给出的答案。 它也适用于类和方法。
我尝试了堆栈溢出的所有方法,以获得在几种情况下都有效的结果。 这是一个对我有用的解决方案。 (关于其他人,这是主观的。)
示例#1
/// <summary>
/// This instance field holds a reference to the
/// <see cref="ConcurrentDictionary{Decimal, Boolean}"/> as
/// <see cref="T:ConcurrentDictionary<decimal, bool?>"/> 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<decimal, bool?> 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<decimal, bool?>"/> that contains
/// the list of all PDF's that are currently opened and being displayed.
/// </summary>
private ConcurrentDictionary<decimal, bool?> openedPdfs = default!;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.