How to reference generic classes and methods in xml documentation
TL;DR:
"How would I reference
FancyClass<T>
?"
/// <see cref="FancyClass{T}"/>
"What about
FancyClass<T>.FancyMethod<K>(T value)
?"
/// <see cref="FancyClass{T}.FancyMethod{K}(T)"/>
"How can I reference a
FancyClass<string>
?"
/// <see cref="SomeType.SomeMethod(FancyClass{string})"/>
/// <see cref="FancyClass{T}"/> whose generic type argument is <see cref="string"/>
While you can reference a method whose signature includes FancyClass<string>
(e.g. as a parameter type), you cannot reference such a closed generic type directly. The second example works around that limitation. (This is seen e.g. on the MSDN refence page for the static System.String.Concat(IEnumerable<string>)
method). :
XML documentation comment cref
rules:
Surround the generic type parameter list with curly braces
{}
instead of with<>
angle brackets. This spares you from escaping the latter as<
and>
— remember, documentation comments are XML!If you include a prefix (such as
T:
for types,M:
for methods,P:
for properties,F:
for fields), the compiler will not perform any validation of the reference, but simply copy thecref
attribute value straight to the documentation XML output. For this reason, you'll have to use the special "ID string" syntax that applies in such files: always use fully-qualified identifiers, and use backticks to reference generic type parameters (`n
on types,``n
on methods).If you omit the prefix, regular language naming rules apply: you can drop namespaces for which there's a
using
statement, and you can use the language's type keywords such asint
instead ofSystem.Int32
. Also, the compiler will check the reference for correctness.
XML documentation comment cref
cheat sheet:
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);
}
}
/// <summary>Uses a <see cref="FancyClass{T}" /> instance.</summary>
BTW, it was present in the MSDN documentation of .Net Framework 2.0 and 3.0, but it disapeared in the version 3.5
To reference the method:
/// <see cref="FancyClass{T}.FancyMethod{K}(T)"/> for more information.