Click or drag to resize
Sandcastle XML Comments Guide

Member ID Strings

All cref attributes on documentation elements such as see or exception generate an ID string in the XML comments file. Normally, the ID string can be properly generated by the compiler based on a partial or fully qualified type or member name. However, there are occasions where this will not work properly. A common example is in C++ code where the compiler is not always able to generate IDs for forward referenced members. In such cases, an ID string can be used as a reference explicitly instead of letting the compiler figure it out.

Note Note

Author Credit: Most of the information in this topic was originally written by Microsoft as part of the .NET Documentation Guidelines document.

The format of the ID string is shown below.

type:fullname[(arglist)]`genericcount

type is one of the following. The final two are specific to the Sandcastle Help File Builder and Tools and are never generated by the compiler.

Type

Description

!

Used by the compiler to indicate an error such as being unable to resolve the member ID

N

Namespace

T

Type (class, interface, structure, enumeration, etc.)

F

Field

E

Event

P

Property

M

Method

R

Sandcastle generated. Represents the root namespace page. There will always be a single entry named R:Project_[HtmlHelpName] where "[HtmlHelpName]" is the value of your project's HTML Help Name property with spaces replaced by underscores. This suffix is required to keep the root namespace container page ID unique across all help files so that there are no duplicate IDs when generating MS Help Viewer output.

O

Sandcastle specific. Used to generate a link to the Overloads List page for an overloaded member.

fullname is the full name of the member from the root. Thus referencing StringBuilder would be System.Text.StringBuilder. The full name will include any member references as well so referencing the Append method of StringBuilder would be System.Text.StringBuilder.Append.

For properties that accept parameters and methods with parameters, the argument list is next. The argument list contains the parentheses as well. Each argument is specified as the full name of the associated type. For reference types, the type name is followed by an at (@) sign. For array types, the type name is followed by brackets ([]). Other symbols are possible but they are not supported by Visual Basic or C#.

For generic classes, the type is followed by a back tick (`) and the number of generic type parameters. For generic methods, there is one back tick (`) and a number for each generic parameter. Additional generic parameters are separated by a comma. Each number is the zero-based index within the parameter list of the parameter.

There are no spaces allowed in the ID string. If a name contains a dot (except to separate namespaces from types, types from other types, and types from members) then the pound (#) sign is used instead. In general, such a member is not possible. However, for referencing special methods like a constructor or explicitly implemented members, it is needed. An example of an explicitly implemented member ID is:

M:TestNamespace.TestClass.System#Collections#IEnumerable#GetEnumerator

The constructor for a type is always of the following form.

M:fullname.#ctor[(arglist)]

The destructor for a class is always of the following form.

M:fullname.Finalize

Operators are encoded as the formal name of the operator followed by their arguments. For conversion operators, the formal name is used (op_Explicit or op_Implicit) followed by the arguments, a tilde (~), and the return type. For example:

M:fullname.op_[binaryOpname](arg1, arg1)
M:fullname.op_[unaryOpname](arg)
M:fullname.op_Explicit(arg1, arg2)~returnType
M:fullname.op_Implicit(arg1, arg2)~returnType

Below are example IDs for each overloadable operator:

Operator

Usage

Member ID Example

+

x = y + z

M:TestDoc.Type1.op_Addition(TestDoc.Type1,TestDoc.Type1)

&

x = y & z

M:TestDoc.Type1.op_BitwiseAnd(TestDoc.Type1,TestDoc.Type1)

|

x = y | z

M:TestDoc.Type1.op_BitwiseOr(TestDoc.Type1,TestDoc.Type1)

--

x--

M:TestDoc.Type1.op_Decrement(TestDoc.Type1)

/

x = y / z

M:TestDoc.Type1.op_Division(TestDoc.Type1,TestDoc.Type1)

==

if(x == y)

M:TestDoc.Type1.op_Equality(TestDoc.Type1,TestDoc.Type1)

^

x = y ^ z

M:TestDoc.Type1.op_ExclusiveOr(TestDoc.Type1,TestDoc.Type1)

explicit

string x = (string)test1Object

M:TestDoc.Type1.op_Explicit(System.String)~TestDoc.Type1

false

if(test1Object == false)

M:TestDoc.Type1.op_False(TestDoc.Type1)

>

if(x > y)

M:TestDoc.Type1.op_GreaterThan(TestDoc.Type1,TestDoc.Type1)

>=

if(x >= y)

M:TestDoc.Type1.op_GreaterThanOrEqual(TestDoc.Type1,TestDoc.Type1)

implicit

string x = test1Object

M:TestDoc.Type1.op_Implicit(TestDoc.Type1)~System.String

++

x++

M:TestDoc.Type1.op_Increment(TestDoc.Type1)

!=

if(x != y)

M:TestDoc.Type1.op_Inequality(TestDoc.Type1,TestDoc.Type1)

<<

x = y << 2

M:TestDoc.Type1.op_LeftShift(TestDoc.Type1,System.Int32)

<

if(x < y)

M:TestDoc.Type1.op_LessThan(TestDoc.Type1,TestDoc.Type1)

<=

if(x <= y)

M:TestDoc.Type1.op_LessThanOrEqual(TestDoc.Type1,TestDoc.Type1)

!

if(!x)

M:TestDoc.Type1.op_LogicalNot(TestDoc.Type1)

%

x = y % z

M:TestDoc.Type1.op_Modulus(TestDoc.Type1,TestDoc.Type1)

*

x = y * z

M:TestDoc.Type1.op_Multiply(TestDoc.Type1,TestDoc.Type1)

~

x = ~x

M:TestDoc.Type1.op_OnesComplement(TestDoc.Type1)

>>

x = y >> 2

M:TestDoc.Type1.op_RightShift(TestDoc.Type1,System.Int32)

-

x = y - z

M:TestDoc.Type1.op_Subtraction(TestDoc.Type1,TestDoc.Type1)

true

if(test1Object == true)

M:TestDoc.Type1.op_True(TestDoc.Type1)

- (unary)

x = -test1Object

M:TestDoc.Type1.op_UnaryNegation(TestDoc.Type1)

+ (unary)

int x = +test1Object

M:TestDoc.Type1.op_UnaryPlus(TestDoc.Type1)

See Also