C#为程序员提供了一种机制,可以使用包含XML文本的特殊注释语法来记录他们的代码。在源代码文件中,具有特定形式的注释可用于指示工具从这些注释和它们之前的源代码元素生成XML。使用这种语法的注释称为文档注释。它们必须紧接在用户定义的类型(例如类,委托或接口)或成员(例如字段,事件,属性或方法)之前。XML生成工具称为文档生成器。(这个生成器可以是,但不一定是C#编译器本身。)文档生成器生成的输出称为文档文件。文档文件用作a的输入文档查看器 ; 用于生成类型信息及其相关文档的某种视觉显示的工具。
此规范建议在文档注释中使用一组标记,但不需要使用这些标记,并且如果需要,可以使用其他标记,只要遵循格式良好的XML的规则。
介绍
具有特殊形式的注释可用于指示工具从这些注释和它们之前的源代码元素生成XML。这样的注释是以三个斜杠(///
)开头的单行注释,或以斜杠和两个星(/**
)开头的分隔注释。它们必须紧接在用户定义的类型(例如类,委托或接口)或它们注释的成员(例如字段,事件,属性或方法)之前。属性部分(属性规范)被视为声明的一部分,因此文档注释必须位于应用于类型或成员的属性之前。
句法:
1 single_line_doc_comment 2 : '///' input_character* 3 ; 4 5 delimited_doc_comment 6 : '/**' delimited_comment_section* asterisk+ '/' 7 ;
在single_line_doc_comment中,如果在与当前single_line_doc_comment相邻的每个single_line_doc_comment上的字符后面有空白字符,那么该空白字符不包含在XML输出中。///
在分隔文档注释中,如果第二行上的第一个非空白字符是星号,并且在分隔文档中的每一行的开头重复相同的可选空格字符和星号字符的模式注释,然后重复模式的字符不包含在XML输出中。该模式可以包括星号字符之后以及之前的空格字符。
例:
1 /// <summary>Class <c>Point</c> models a point in a two-dimensional 2 /// plane.</summary> 3 /// 4 public class Point 5 { 6 /// <summary>method <c>draw</c> renders the point.</summary> 7 void draw() {...} 8 }
文档注释中的文本必须根据XML规则(http://www.w3.org/TR/REC-xml)很好地形成。如果XML格式不正确,则会生成警告,文档文件将包含一条注释,说明遇到了错误。
虽然开发人员可以自由创建自己的标记集,但推荐标记中定义了推荐集。一些推荐的标签具有特殊含义:
- 该
<param>
标签是用来描述参数。如果使用此类标记,则文档生成器必须验证指定的参数是否存在,以及文档注释中是否描述了所有参数。如果此类验证失败,则文档生成器会发出警告。 - 该
cref
属性可以附加到任何标记以提供对代码元素的引用。文档生成器必须验证此代码元素是否存在。如果验证失败,文档生成器会发出警告。在查找cref
属性中描述的名称时,文档生成器必须根据using
源代码中出现的语句来遵循名称空间可见性。对于通用的代码元素,不能使用普通的通用语法(即“List<T>
”),因为它会生成无效的XML。可以使用大括号代替括号(即“List{T}
”),或者可以使用XML转义语法(即“List<T>
”)。 - 该
<summary>
标记旨在供文档查看器用于显示有关类型或成员的其他信息。 - 该
<include>
标签包括从外部XML文件的信息。
请注意,文档文件不提供有关类型和成员的完整信息(例如,它不包含任何类型信息)。要获取有关类型或成员的此类信息,必须将文档文件与实际类型或成员的反射结合使用。
常用标签
文档生成器必须接受并处理根据XML规则有效的任何标记。以下标记提供用户文档中常用的功能。(当然,其他标签也是可能的。)
标签 | 部分 | 目的 |
---|---|---|
<c> |
<c> |
以类似代码的字体设置文本 |
<code> |
<code> |
设置一行或多行源代码或程序输出 |
<example> |
<example> |
表示一个例子 |
<exception> |
<exception> |
标识方法可以抛出的异常 |
<include> |
<include> |
包含来自外部文件的XML |
<list> |
<list> |
创建列表或表 |
<para> |
<para> |
允许添加到文本的结构 |
<param> |
<param> |
描述方法或构造函数的参数 |
<paramref> |
<paramref> |
确定单词是参数名称 |
<permission> |
<permission> |
记录成员的安全可访问性 |
<remark> |
<remark> |
描述有关类型的其他信息 |
<returns> |
<returns> |
描述方法的返回值 |
<see> |
<see> |
指定链接 |
<seealso> |
<seealso> |
生成另请参阅条目 |
<summary> |
<summary> |
描述类型或类型的成员 |
<value> |
<value> |
描述一处房产 |
<typeparam> |
描述泛型类型参数 | |
<typeparamref> |
确定单词是类型参数名称 |
<c>
此标记提供了一种机制,用于指示描述中的文本片段应设置为特殊字体,例如用于代码块的字体。对于实际代码行,请使用<code>
(<code>
)。
句法:
<c>text</c>
例:
1 /// <summary>Class <c>Point</c> models a point in a two-dimensional 2 /// plane.</summary> 3 4 public class Point 5 { 6 // ... 7 }
<code>
此标记用于以某种特殊字体设置一行或多行源代码或程序输出。对于叙述中的小代码片段,请使用<c>
(<c>
)。
句法:
<code>source code or program output</code>
例:
1 /// <summary>This method changes the point's location by 2 /// the given x- and y-offsets. 3 /// <example>For example: 4 /// <code> 5 /// Point p = new Point(3,5); 6 /// p.Translate(-1,3); 7 /// </code> 8 /// results in <c>p</c>'s having the value (2,8). 9 /// </example> 10 /// </summary> 11 12 public void Translate(int xor, int yor) { 13 X += xor; 14 Y += yor; 15 }
<example>
此标记允许注释中的示例代码,以指定如何使用方法或其他库成员。通常,这也涉及使用tag <code>
(<code>
)。
句法:
<example>description</example>
例:
有关示例,请参阅<code>
(<code>
)。
<exception>
此标记提供了一种记录方法可以抛出的异常的方法。
句法:
<exception cref="member">description</exception>
member
是会员的名字。文档生成器检查给定成员是否存在,并转换member
为文档文件中的规范元素名称。description
是对抛出异常的情况的描述。
例:
1 public class DataBaseOperations 2 { 3 /// <exception cref="MasterFileFormatCorruptException"></exception> 4 /// <exception cref="MasterFileLockedOpenException"></exception> 5 public static void ReadRecord(int flag) { 6 if (flag == 1) 7 throw new MasterFileFormatCorruptException(); 8 else if (flag == 2) 9 throw new MasterFileLockedOpenException(); 10 // ... 11 } 12 }
<include>
此标记允许包含源代码文件外部的XML文档的信息。外部文件必须是格式良好的XML文档,并且XPath表达式应用于该文档以指定要包含的文档中的XML。该<include>
标签,然后用从外部文件所选择的XML替换。
句法:
<include file="filename" path="xpath" />
filename
是外部XML文件的文件名。文件名相对于包含include标记的文件进行解释。xpath
是一个XPath表达式,用于选择外部XML文件中的某些XML。
例:
如果源代码包含如下声明:
1 /// <include file="docs.xml" path='extradoc/class[@name="IntList"]/*' /> 2 public class IntList { ... }
外部文件“docs.xml”具有以下内容:
1 <?xml version="1.0"?> 2 <extradoc> 3 <class name="IntList"> 4 <summary> 5 Contains a list of integers. 6 </summary> 7 </class> 8 <class name="StringList"> 9 <summary> 10 Contains a list of integers. 11 </summary> 12 </class> 13 </extradoc>
然后输出相同的文档,就好像源代码包含:
1 /// <summary> 2 /// Contains a list of integers. 3 /// </summary> 4 public class IntList { ... }
<list>
此标记用于创建项目列表或表。它可能包含一个<listheader>
块来定义表或定义列表的标题行。(定义表时,只term
需要提供标题中的条目。)
列表中的每个项目都使用<item>
块指定。当创建一个定义列表,无论是term
和description
必须指定。但是,对于表,项目符号列表或编号列表,只description
需要指定。
句法:
1 <list type="bullet" | "number" | "table"> 2 <listheader> 3 <term>term</term> 4 <description>*description*</description> 5 </listheader> 6 <item> 7 <term>term</term> 8 <description>*description*</description> 9 </item> 10 ... 11 <item> 12 <term>term</term> 13 <description>description</description> 14 </item> 15 </list>
term
是定义的术语,其定义是description
。description
是子弹或编号列表中的项目,或者是a的定义term
。
例:
1 public class MyClass 2 { 3 /// <summary>Here is an example of a bulleted list: 4 /// <list type="bullet"> 5 /// <item> 6 /// <description>Item 1.</description> 7 /// </item> 8 /// <item> 9 /// <description>Item 2.</description> 10 /// </item> 11 /// </list> 12 /// </summary> 13 public static void Main () { 14 // ... 15 } 16 }
<para>
此标记用于其他标记内,例如<summary>
(<remark>
)或<returns>
(<returns>
),并允许将结构添加到文本中。
句法:
<para>content</para>
content
该段落的文本在哪里。
例:
1 /// <summary>This is the entry point of the Point class testing program. 2 /// <para>This program tests each method and operator, and 3 /// is intended to be run after any non-trivial maintenance has 4 /// been performed on the Point class.</para></summary> 5 public static void Main() { 6 // ... 7 }
<param>
此标记用于描述方法,构造函数或索引器的参数。
句法:
<param name="name">description</param>
name
是参数的名称。description
是参数的描述。
例:
1 /// <summary>This method changes the point's location to 2 /// the given coordinates.</summary> 3 /// <param name="xor">the new x-coordinate.</param> 4 /// <param name="yor">the new y-coordinate.</param> 5 public void Move(int xor, int yor) { 6 X = xor; 7 Y = yor; 8 }
<paramref>
此标记用于指示单词是参数。可以处理文档文件以便以某种不同的方式格式化此参数。
句法:
<paramref name="name"/>
其中name
是参数的名称。
例:
1 /// <summary>This constructor initializes the new Point to 2 /// (<paramref name="xor"/>,<paramref name="yor"/>).</summary> 3 /// <param name="xor">the new Point's x-coordinate.</param> 4 /// <param name="yor">the new Point's y-coordinate.</param> 5 6 public Point(int xor, int yor) { 7 X = xor; 8 Y = yor; 9 }
<permission>
此标记允许记录成员的安全可访问性。
句法:
<permission cref="member">description</permission>
member
是会员的名字。文档生成器检查给定的代码元素是否存在,并将成员转换为文档文件中的规范元素名称。description
是对成员的访问权限的描述。
例:
1 /// <permission cref="System.Security.PermissionSet">Everyone can 2 /// access this method.</permission> 3 4 public static void Test() { 5 // ... 6 }
<remark>
此标记用于指定有关类型的额外信息。(使用<summary>
(<summary>
)来描述类型本身和类型的成员。)
句法:
<remark>description</remark>
description
评论的文字在哪里。
例:
1 /// <summary>Class <c>Point</c> models a point in a 2 /// two-dimensional plane.</summary> 3 /// <remark>Uses polar coordinates</remark> 4 public class Point 5 { 6 // ... 7 }
<returns>
此标记用于描述方法的返回值。
句法:
<returns>description</returns>
其中description
是返回值的描述。
例:
1 /// <summary>Report a point's location as a string.</summary> 2 /// <returns>A string representing a point's location, in the form (x,y), 3 /// without any leading, trailing, or embedded whitespace.</returns> 4 public override string ToString() { 5 return "(" + X + "," + Y + ")"; 6 }
<see>
此标记允许在文本中指定链接。使用<seealso>
(<seealso>
)指示要在“另请参阅”部分中显示的文本。
句法:
<see cref="member"/>
其中member
是成员的名称。文档生成器检查给定的代码元素是否存在,并将成员更改为生成的文档文件中的元素名称。
例:
1 /// <summary>This method changes the point's location to 2 /// the given coordinates.</summary> 3 /// <see cref="Translate"/> 4 public void Move(int xor, int yor) { 5 X = xor; 6 Y = yor; 7 } 8 9 /// <summary>This method changes the point's location by 10 /// the given x- and y-offsets. 11 /// </summary> 12 /// <see cref="Move"/> 13 public void Translate(int xor, int yor) { 14 X += xor; 15 Y += yor; 16 }
<seealso>
此标记允许为“另请参阅”部分生成条目。使用<see>
(<see>
)从文本中指定链接。
句法:
<seealso cref="member"/>
其中member
是成员的名称。文档生成器检查给定的代码元素是否存在,并将成员更改为生成的文档文件中的元素名称。
例:
1 /// <summary>This method determines whether two Points have the same 2 /// location.</summary> 3 /// <seealso cref="operator=="/> 4 /// <seealso cref="operator!="/> 5 public override bool Equals(object o) { 6 // ... 7 }
<summary>
此标记可用于描述类型或类型的成员。使用<remark>
(<remark>
)来描述类型本身。
句法:
<summary>description</summary>
description
是类型或成员的摘要。
例:
1 /// <summary>This constructor initializes the new Point to (0,0).</summary> 2 public Point() : this(0,0) { 3 }
<value>
此标记允许描述属性。
句法:
<value>property description</value>
property description
是该物业的描述。
例:
1 /// <value>Property <c>X</c> represents the point's x-coordinate.</value> 2 public int X 3 { 4 get { return x; } 5 set { x = value; } 6 }
<typeparam>
此标记用于描述类,结构,接口,委托或方法的泛型类型参数。
句法:
<typeparam name="name">description</typeparam>
其中name
是type参数的名称,description
是其描述。
例:
1 /// <summary>A generic list class.</summary> 2 /// <typeparam name="T">The type stored by the list.</typeparam> 3 public class MyList<T> { 4 ... 5 }
<typeparamref>
此标记用于指示单词是类型参数。可以处理文档文件以某种不同的方式格式化此类型参数。
句法:
<typeparamref name="name"/>
name
参数的名称。
例:
1 /// <summary>This method fetches data and returns a list of <typeparamref name="T"/>.</summary> 2 /// <param name="query">query to execute</param> 3 public List<T> FetchData<T>(string query) { 4 ... 5 }
处理文档文件
文档生成器为源代码中的每个元素生成一个ID字符串,该元素标记有文档注释。此ID字符串唯一标识源元素。文档查看器可以使用ID字符串来标识文档适用的相应元数据/反射项。
文档文件不是源代码的分层表示; 相反,它是一个平面列表,每个元素都有一个生成的ID字符串。
ID字符串格式
文档生成器在生成ID字符串时遵循以下规则:
-
字符串中没有放置空格。
-
字符串的第一部分通过单个字符后跟冒号来标识要记录的成员类型。定义了以下类型的成员:
字符 描述 和 事件 F 领域 中号 方法(包括构造函数,析构函数和运算符) ñ 命名空间 P 属性(包括指数) Ť 类型(例如类,委托,枚举,接口和结构) ! 错误字符串; 字符串的其余部分提供有关错误的信息。例如,文档生成器为无法解析的链接生成错误信息。 -
字符串的第二部分是元素的完全限定名称,从名称空间的根开始。元素的名称,其封闭类型和命名空间由句点分隔。如果项目的名称本身具有句点,则它们将替换为
#(U+0023)
字符。(假设没有元素在其名称中包含此字符。) - 对于带参数的方法和属性,参数列表如下,括在括号中。对于那些没有参数的人,省略了括号。参数用逗号分隔。每个参数的编码与CLI签名相同,如下所示:
- 参数由其文档名称表示,该名称基于其完全限定名称,修改如下:
- 表示泛型类型的参数具有附加的“'”字符,后跟类型参数的数量
- 具有
out
orref
修饰符的参数具有@
以下类型名称。通过值或通过的参数params
没有特殊符号。 - 作为数组的参数表示为
[lowerbound:size, ... , lowerbound:size]
逗号的数量小于1,并且每个维度的下限和大小(如果已知)以十进制表示。如果未指定下限或大小,则省略它。如果省略特定尺寸的下限和尺寸,则也省略“:
”。锯齿状数组[]
每个级别用一个“ ” 表示。 - 具有除void之外的指针类型的参数使用
*
以下类型名称表示。void指针使用类型名称表示System.Void
。 - 引用类型上定义的泛型类型参数的参数使用“`”字符后跟类型参数的从零开始的索引进行编码。
- 使用方法中定义的泛型类型参数的参数使用双重反引号“`”而不是用于类型的“`”。
- 引用构造泛型类型的参数使用泛型类型进行编码,后跟“{”,后跟逗号分隔的类型参数列表,后跟“}”。
- 参数由其文档名称表示,该名称基于其完全限定名称,修改如下:
ID字符串示例
以下示例显示了C#代码的一个片段,以及从能够具有文档注释的每个源元素生成的ID字符串:
-
类型使用其完全限定名称表示,并使用通用信息进行扩充:
1 enum Color { Red, Blue, Green } 2 3 namespace Acme 4 { 5 interface IProcess {...} 6 7 struct ValueType {...} 8 9 class Widget: IProcess 10 { 11 public class NestedClass {...} 12 public interface IMenuItem {...} 13 public delegate void Del(int i); 14 public enum Direction { North, South, East, West } 15 } 16 17 class MyList<T> 18 { 19 class Helper<U,V> {...} 20 } 21 } 22 23 "T:Color" 24 "T:Acme.IProcess" 25 "T:Acme.ValueType" 26 "T:Acme.Widget" 27 "T:Acme.Widget.NestedClass" 28 "T:Acme.Widget.IMenuItem" 29 "T:Acme.Widget.Del" 30 "T:Acme.Widget.Direction" 31 "T:Acme.MyList`1" 32 "T:Acme.MyList`1.Helper`2"
字段由其完全限定名称表示:
1 namespace Acme 2 { 3 struct ValueType 4 { 5 private int total; 6 } 7 8 class Widget: IProcess 9 { 10 public class NestedClass 11 { 12 private int value; 13 } 14 15 private string message; 16 private static Color defaultColor; 17 private const double PI = 3.14159; 18 protected readonly double monthlyAverage; 19 private long[] array1; 20 private Widget[,] array2; 21 private unsafe int *pCount; 22 private unsafe float **ppValues; 23 } 24 } 25 26 "F:Acme.ValueType.total" 27 "F:Acme.Widget.NestedClass.value" 28 "F:Acme.Widget.message" 29 "F:Acme.Widget.defaultColor" 30 "F:Acme.Widget.PI" 31 "F:Acme.Widget.monthlyAverage" 32 "F:Acme.Widget.array1" 33 "F:Acme.Widget.array2" 34 "F:Acme.Widget.pCount" 35 "F:Acme.Widget.ppValues"
构造函数。
1 namespace Acme 2 { 3 class Widget: IProcess 4 { 5 static Widget() {...} 6 public Widget() {...} 7 public Widget(string s) {...} 8 } 9 } 10 11 "M:Acme.Widget.#cctor" 12 "M:Acme.Widget.#ctor" 13 "M:Acme.Widget.#ctor(System.String)"
析构函数
1 namespace Acme 2 { 3 class Widget: IProcess 4 { 5 ~Widget() {...} 6 } 7 } 8 9 "M:Acme.Widget.Finalize"
方法。
1 namespace Acme 2 { 3 struct ValueType 4 { 5 public void M(int i) {...} 6 } 7 8 class Widget: IProcess 9 { 10 public class NestedClass 11 { 12 public void M(int i) {...} 13 } 14 15 public static void M0() {...} 16 public void M1(char c, out float f, ref ValueType v) {...} 17 public void M2(short[] x1, int[,] x2, long[][] x3) {...} 18 public void M3(long[][] x3, Widget[][,,] x4) {...} 19 public unsafe void M4(char *pc, Color **pf) {...} 20 public unsafe void M5(void *pv, double *[][,] pd) {...} 21 public void M6(int i, params object[] args) {...} 22 } 23 24 class MyList<T> 25 { 26 public void Test(T t) { } 27 } 28 29 class UseList 30 { 31 public void Process(MyList<int> list) { } 32 public MyList<T> GetValues<T>(T inputValue) { return null; } 33 } 34 } 35 36 "M:Acme.ValueType.M(System.Int32)" 37 "M:Acme.Widget.NestedClass.M(System.Int32)" 38 "M:Acme.Widget.M0" 39 "M:Acme.Widget.M1(System.Char,System.Single@,Acme.ValueType@)" 40 "M:Acme.Widget.M2(System.Int16[],System.Int32[0:,0:],System.Int64[][])" 41 "M:Acme.Widget.M3(System.Int64[][],Acme.Widget[0:,0:,0:][])" 42 "M:Acme.Widget.M4(System.Char*,Color**)" 43 "M:Acme.Widget.M5(System.Void*,System.Double*[0:,0:][])" 44 "M:Acme.Widget.M6(System.Int32,System.Object[])" 45 "M:Acme.MyList`1.Test(`0)" 46 "M:Acme.UseList.Process(Acme.MyList{System.Int32})" 47 "M:Acme.UseList.GetValues``(``0)"
属性和索引器。
1 namespace Acme 2 { 3 class Widget: IProcess 4 { 5 public int Width { get {...} set {...} } 6 public int this[int i] { get {...} set {...} } 7 public int this[string s, int i] { get {...} set {...} } 8 } 9 } 10 11 "P:Acme.Widget.Width" 12 "P:Acme.Widget.Item(System.Int32)" 13 "P:Acme.Widget.Item(System.String,System.Int32)"
事件
1 namespace Acme 2 { 3 class Widget: IProcess 4 { 5 public event Del AnEvent; 6 } 7 } 8 9 "E:Acme.Widget.AnEvent"
一元运算符。
1 namespace Acme 2 { 3 class Widget: IProcess 4 { 5 public static Widget operator+(Widget x) {...} 6 } 7 } 8 9 "M:Acme.Widget.op_UnaryPlus(Acme.Widget)"
全套使用一元运算符函数名称如下:op_UnaryPlus
,op_UnaryNegation
,op_LogicalNot
,op_OnesComplement
,op_Increment
,op_Decrement
,op_True
,和op_False
。
二元运算符。
1 namespace Acme 2 { 3 class Widget: IProcess 4 { 5 public static Widget operator+(Widget x1, Widget x2) {...} 6 } 7 } 8 9 "M:Acme.Widget.op_Addition(Acme.Widget,Acme.Widget)"
一套完整的用于二元运算符函数名称如下:op_Addition
,op_Subtraction
,op_Multiply
,op_Division
,op_Modulus
,op_BitwiseAnd
,op_BitwiseOr
,op_ExclusiveOr
,op_LeftShift
,op_RightShift
,op_Equality
,op_Inequality
,op_LessThan
,op_LessThanOrEqual
,op_GreaterThan
,和op_GreaterThanOrEqual
。
转换运算符~
后跟返回类型后跟“ ”。
1 namespace Acme 2 { 3 class Widget: IProcess 4 { 5 public static explicit operator int(Widget x) {...} 6 public static implicit operator long(Widget x) {...} 7 } 8 } 9 10 "M:Acme.Widget.op_Explicit(Acme.Widget)~System.Int32" 11 "M:Acme.Widget.op_Implicit(Acme.Widget)~System.Int64"
一个例子
C#源代码
以下示例显示了Point
类的源代码:
1 namespace Graphics 2 { 3 4 /// <summary>Class <c>Point</c> models a point in a two-dimensional plane. 5 /// </summary> 6 public class Point 7 { 8 9 /// <summary>Instance variable <c>x</c> represents the point's 10 /// x-coordinate.</summary> 11 private int x; 12 13 /// <summary>Instance variable <c>y</c> represents the point's 14 /// y-coordinate.</summary> 15 private int y; 16 17 /// <value>Property <c>X</c> represents the point's x-coordinate.</value> 18 public int X 19 { 20 get { return x; } 21 set { x = value; } 22 } 23 24 /// <value>Property <c>Y</c> represents the point's y-coordinate.</value> 25 public int Y 26 { 27 get { return y; } 28 set { y = value; } 29 } 30 31 /// <summary>This constructor initializes the new Point to 32 /// (0,0).</summary> 33 public Point() : this(0,0) {} 34 35 /// <summary>This constructor initializes the new Point to 36 /// (<paramref name="xor"/>,<paramref name="yor"/>).</summary> 37 /// <param><c>xor</c> is the new Point's x-coordinate.</param> 38 /// <param><c>yor</c> is the new Point's y-coordinate.</param> 39 public Point(int xor, int yor) { 40 X = xor; 41 Y = yor; 42 } 43 44 /// <summary>This method changes the point's location to 45 /// the given coordinates.</summary> 46 /// <param><c>xor</c> is the new x-coordinate.</param> 47 /// <param><c>yor</c> is the new y-coordinate.</param> 48 /// <see cref="Translate"/> 49 public void Move(int xor, int yor) { 50 X = xor; 51 Y = yor; 52 } 53 54 /// <summary>This method changes the point's location by 55 /// the given x- and y-offsets. 56 /// <example>For example: 57 /// <code> 58 /// Point p = new Point(3,5); 59 /// p.Translate(-1,3); 60 /// </code> 61 /// results in <c>p</c>'s having the value (2,8). 62 /// </example> 63 /// </summary> 64 /// <param><c>xor</c> is the relative x-offset.</param> 65 /// <param><c>yor</c> is the relative y-offset.</param> 66 /// <see cref="Move"/> 67 public void Translate(int xor, int yor) { 68 X += xor; 69 Y += yor; 70 } 71 72 /// <summary>This method determines whether two Points have the same 73 /// location.</summary> 74 /// <param><c>o</c> is the object to be compared to the current object. 75 /// </param> 76 /// <returns>True if the Points have the same location and they have 77 /// the exact same type; otherwise, false.</returns> 78 /// <seealso cref="operator=="/> 79 /// <seealso cref="operator!="/> 80 public override bool Equals(object o) { 81 if (o == null) { 82 return false; 83 } 84 85 if (this == o) { 86 return true; 87 } 88 89 if (GetType() == o.GetType()) { 90 Point p = (Point)o; 91 return (X == p.X) && (Y == p.Y); 92 } 93 return false; 94 } 95 96 /// <summary>Report a point's location as a string.</summary> 97 /// <returns>A string representing a point's location, in the form (x,y), 98 /// without any leading, training, or embedded whitespace.</returns> 99 public override string ToString() { 100 return "(" + X + "," + Y + ")"; 101 } 102 103 /// <summary>This operator determines whether two Points have the same 104 /// location.</summary> 105 /// <param><c>p1</c> is the first Point to be compared.</param> 106 /// <param><c>p2</c> is the second Point to be compared.</param> 107 /// <returns>True if the Points have the same location and they have 108 /// the exact same type; otherwise, false.</returns> 109 /// <seealso cref="Equals"/> 110 /// <seealso cref="operator!="/> 111 public static bool operator==(Point p1, Point p2) { 112 if ((object)p1 == null || (object)p2 == null) { 113 return false; 114 } 115 116 if (p1.GetType() == p2.GetType()) { 117 return (p1.X == p2.X) && (p1.Y == p2.Y); 118 } 119 120 return false; 121 } 122 123 /// <summary>This operator determines whether two Points have the same 124 /// location.</summary> 125 /// <param><c>p1</c> is the first Point to be compared.</param> 126 /// <param><c>p2</c> is the second Point to be compared.</param> 127 /// <returns>True if the Points do not have the same location and the 128 /// exact same type; otherwise, false.</returns> 129 /// <seealso cref="Equals"/> 130 /// <seealso cref="operator=="/> 131 public static bool operator!=(Point p1, Point p2) { 132 return !(p1 == p2); 133 } 134 135 /// <summary>This is the entry point of the Point class testing 136 /// program. 137 /// <para>This program tests each method and operator, and 138 /// is intended to be run after any non-trivial maintenance has 139 /// been performed on the Point class.</para></summary> 140 public static void Main() { 141 // class test code goes here 142 } 143 } 144 }
产生的XML
以下是给定类的源代码时由一个文档生成器生成的输出Point
,如上所示:
1 <?xml version="1.0"?> 2 <doc> 3 <assembly> 4 <name>Point</name> 5 </assembly> 6 <members> 7 <member name="T:Graphics.Point"> 8 <summary>Class <c>Point</c> models a point in a two-dimensional 9 plane. 10 </summary> 11 </member> 12 13 <member name="F:Graphics.Point.x"> 14 <summary>Instance variable <c>x</c> represents the point's 15 x-coordinate.</summary> 16 </member> 17 18 <member name="F:Graphics.Point.y"> 19 <summary>Instance variable <c>y</c> represents the point's 20 y-coordinate.</summary> 21 </member> 22 23 <member name="M:Graphics.Point.#ctor"> 24 <summary>This constructor initializes the new Point to 25 (0,0).</summary> 26 </member> 27 28 <member name="M:Graphics.Point.#ctor(System.Int32,System.Int32)"> 29 <summary>This constructor initializes the new Point to 30 (<paramref name="xor"/>,<paramref name="yor"/>).</summary> 31 <param><c>xor</c> is the new Point's x-coordinate.</param> 32 <param><c>yor</c> is the new Point's y-coordinate.</param> 33 </member> 34 35 <member name="M:Graphics.Point.Move(System.Int32,System.Int32)"> 36 <summary>This method changes the point's location to 37 the given coordinates.</summary> 38 <param><c>xor</c> is the new x-coordinate.</param> 39 <param><c>yor</c> is the new y-coordinate.</param> 40 <see cref="M:Graphics.Point.Translate(System.Int32,System.Int32)"/> 41 </member> 42 43 <member 44 name="M:Graphics.Point.Translate(System.Int32,System.Int32)"> 45 <summary>This method changes the point's location by 46 the given x- and y-offsets. 47 <example>For example: 48 <code> 49 Point p = new Point(3,5); 50 p.Translate(-1,3); 51 </code> 52 results in <c>p</c>'s having the value (2,8). 53 </example> 54 </summary> 55 <param><c>xor</c> is the relative x-offset.</param> 56 <param><c>yor</c> is the relative y-offset.</param> 57 <see cref="M:Graphics.Point.Move(System.Int32,System.Int32)"/> 58 </member> 59 60 <member name="M:Graphics.Point.Equals(System.Object)"> 61 <summary>This method determines whether two Points have the same 62 location.</summary> 63 <param><c>o</c> is the object to be compared to the current 64 object. 65 </param> 66 <returns>True if the Points have the same location and they have 67 the exact same type; otherwise, false.</returns> 68 <seealso 69 cref="M:Graphics.Point.op_Equality(Graphics.Point,Graphics.Point)"/> 70 <seealso 71 cref="M:Graphics.Point.op_Inequality(Graphics.Point,Graphics.Point)"/> 72 </member> 73 74 <member name="M:Graphics.Point.ToString"> 75 <summary>Report a point's location as a string.</summary> 76 <returns>A string representing a point's location, in the form 77 (x,y), 78 without any leading, training, or embedded whitespace.</returns> 79 </member> 80 81 <member 82 name="M:Graphics.Point.op_Equality(Graphics.Point,Graphics.Point)"> 83 <summary>This operator determines whether two Points have the 84 same 85 location.</summary> 86 <param><c>p1</c> is the first Point to be compared.</param> 87 <param><c>p2</c> is the second Point to be compared.</param> 88 <returns>True if the Points have the same location and they have 89 the exact same type; otherwise, false.</returns> 90 <seealso cref="M:Graphics.Point.Equals(System.Object)"/> 91 <seealso 92 cref="M:Graphics.Point.op_Inequality(Graphics.Point,Graphics.Point)"/> 93 </member> 94 95 <member 96 name="M:Graphics.Point.op_Inequality(Graphics.Point,Graphics.Point)"> 97 <summary>This operator determines whether two Points have the 98 same 99 location.</summary> 100 <param><c>p1</c> is the first Point to be compared.</param> 101 <param><c>p2</c> is the second Point to be compared.</param> 102 <returns>True if the Points do not have the same location and 103 the 104 exact same type; otherwise, false.</returns> 105 <seealso cref="M:Graphics.Point.Equals(System.Object)"/> 106 <seealso 107 cref="M:Graphics.Point.op_Equality(Graphics.Point,Graphics.Point)"/> 108 </member> 109 110 <member name="M:Graphics.Point.Main"> 111 <summary>This is the entry point of the Point class testing 112 program. 113 <para>This program tests each method and operator, and 114 is intended to be run after any non-trivial maintenance has 115 been performed on the Point class.</para></summary> 116 </member> 117 118 <member name="P:Graphics.Point.X"> 119 <value>Property <c>X</c> represents the point's 120 x-coordinate.</value> 121 </member> 122 123 <member name="P:Graphics.Point.Y"> 124 <value>Property <c>Y</c> represents the point's 125 y-coordinate.</value> 126 </member> 127 </members> 128 </doc>