10
XML Documentation
XML is used extensively to
document program code. Apart from its status of a mere acronym for eXtensible
Markup Language, XML has a bounden duty to achieve miracles. However, in this chapter,
we would be utilizing XML for the temporal task of documenting our code.
a.cs
class zzz
{
public static void Main() {
}
}
Run the compiler as
>csc a.cs /doc:a.xml
a.xml
<?xml version="1.0"?>
<doc>
<assembly>
<name>a</name>
</assembly>
<members>
</members>
</doc>
This is the smallest possible
XML file that can be effectively generated by the compiler. The compiler with
the /doc option, followed by a colon and filename, creates the XML file, which
documents the C# program.
Anything placed within the
<> brackets is called a tag. At the expense of sounding tediously
repetitive, we once again reiterate that, each and every XML file must
necessarily start with a tag beginning with <?xml>. This has to be followed
by an attribute called version. Presently, the only permissible value that can
be assigned to version is 1.0. There may never be a version 1.1 or 2.0.
Subsequent to this, a root tag
called 'doc' is specified, which envelopes all other tags within the file. We
have a tag called 'assembly' which owns another tag called 'name' that encloses
our assembly name 'a'. The name of our program file is 'a'. There are no
members to be documented, therefore, no names are noticeable within the member
tags. This is the basic structure of our XML file.
It is the bare minimum, no
frills structure, created by the compiler. Now, let us refurbish and garnish it
through our own contribution.
a.cs
class zzz
{
/// <vijay>
public static void Main()
{
}
}
We have added an XML tag in the
.cs file. The documentation clearly states that an XML tag in a .cs file cannot
begin with two slashes, since they are reserved for comments. It should instead
have three slashes. The use of the two slashes generates the following warning:
Output
a.cs(4,3): warning CS1570: XML comment on 'zzz.Main()' has badly formed XML -- 'End tag 'member' does not match the start tag 'vijay'.'
From now on, we shall only
display the pertinent portions of the XML file, while ignoring the portion that
is invariant, such as, the doc and the /doc tags. So in the file created as:
a.xml
<?xml version="1.0"?>
<doc>
<assembly>
<name>a</name>
</assembly>
<members>
<!-- Badly formed XML comment ignored for member "M:zzz.Main" -->
</members>
</doc>
we will display only
xml fragment:
<members>
<!-- Badly formed XML comment ignored for member "M:zzz.Main" -->
</members>
In the next program, a closing
tag of 'vijay' is specified.
a.cs
class zzz
{
/// <vijay>
/// Function Main gets called first
/// </vijay>
public static void Main()
{
}
}
xml
<members>
<member name="M:zzz.Main">
<vijay>
Function Main gets called first
</vijay>
</member>
</members>
The earlier program generated an
error, since there was no corresponding end tag to the tag 'vijay'.
Every tag in XML must
necessarily have a start tag and an end tag. We are at liberty to choose any
name for the tag. Therefore, we have chosen the name 'vijay'.
The compiler creates a tag
called 'member' under the tag members, and adds an attribute called 'name'.
This attribute is initialized to the name of the C# entity, which is the
position where the tag is placed. The value assigned to name is, as follows:
• The letter M,
• Followed by a colon separator,
• Followed by the name of the class zzz,
• Followed by a dot separator
• Finally, followed by the name of the function i.e. Main.
Thus, it displays M:zzz.Main.
The tag 'vijay' and the text enclosed
between the start and end tags of 'vijay' subsequently, get enclosed within the
members tag.
a.cs
/// <mukhi>
/// Our first class
/// </mukhi>
class zzz
{
/// <vijay>
/// Function Main gets called first
/// </vijay>
public static void Main()
{
}
}
xml
<members>
<member name="T:zzz">
<mukhi>
Our first class
</mukhi>
</member>
<member name="M:zzz.Main">
<vijay>
Function Main gets called first
</vijay>
</member>
</members>
Now, we have added a tag called
'mukhi' to the class. It is however, not added to the function. So presently,
there are two member tags, and each has been assigned a name within the members
tag. The value assigned to the member name, which encloses 'mukhi' is, T:zzz.
This is created in a manner akin to that of a function, with the exception of
the prefix M, which has now been replaced by T.
The rationale behind introducing
XML tags is that, a program known as an XML Parser can interpret the above XML
file, and subsequently, create legible output. But, the prime impediment that
we have to confront and surmount is, the reluctance of programmers to document
code in the first place.
a.cs
class zzz
{
/// <mukhi>
/// Our Instance Variable
/// </mukhi>
public int i;
public static void Main()
{
/// <vijay>
/// Our first variable ii
/// </vijay>
int ii;
}
}
Output
a.cs(12,5): warning CS0168: The variable 'ii' is declared but never used
a.cs(9,1): warning CS1587: XML comment is not placed on a valid language element
a.cs(6,12): warning CS0649: Field 'zzz.i' is never assigned to, and will always have its default value 0
xml
<members>
<member name="F:zzz.i">
<mukhi>
Our Instance Variable
</mukhi>
</member>
</members>
Oops! The tags that we give
within a function have not been reflected in the XML file. The instance
variable i is flagged with an F, but the local variable ii is not reflected in
the XML file at all.
We have carried this out on
purpose, with the intention of demonstrating that it is not permissible to
write XML tags within functions. Even though our preceding action would not
produce any error, the compiler shall, in any case, ignore our work of art.
We will now dwell upon the names
or string ids, which the compiler generates for names of entities. They are as
follows:
• N stands for a Namespace.
• T represents a type, class, interface, struct, enum and delegate.
• F denotes a field.
• P is indicative of either properties or indexers.
• M indicates all methods
• E represents an event.
• ! is indicative of an error.
a.cs
/// <vijay>
/// Our first variable ii
/// </vijay>
namespace aaa
{
class zzz
{
public static void Main()
{
}
}
}
Output
a.cs(1,1): warning CS1587: XML comment is not placed on a valid language element
We do not enjoy the license to
place tags wherever we desire. Thus, a warning is issued when a tag is placed
on a namespace, although no error is generated. In the earlier case too, a
similar warning was issued, when we had placed the tags in a function.
a.cs
class zzz
{
/// <vijay>
/// Our function <c>Main</c> is the starting point
/// </vijay>
public static void Main()
{
}
}
xml
<member name="M:zzz.Main">
<vijay>
Our function <c>Main</c> is the starting point
</vijay>
</member>
If we place the tag <c>
and </c> around some text in a tag, the tag gets copied verbatim, into
the XML file. It is indicative of the fact that the text represents some code.
To mark multiple lines of code, the code tag may be used instead. The example
tag also works in a similar manner.
a.cs
/// <exception cref="System.Exception"> Our exception class </exception>
class zzz
{
public static void Main()
{
}
}
xml
<member name="T:zzz">
<exception cref="T:System.Exception"> Our exception class </exception>
</member>
The exception tag works as
demonstrated above, with a single difference in that, the attribute cref is
inspected for accuracy. This attribute should represent a valid C# entity,
otherwise, the following warning is displayed:
/// <exception cref="System.Exceptions"> Our exception class </exception>
Output
a.cs(2,22): warning CS1574: XML comment on 'zzz' has cref attribute 'System.Exceptions' that could not be found.
xml
<member name="T:zzz">
<exception cref="!:System.Exceptions"> Our exception class </exception>
</member>
All the tags expounded by us so
far, have a similar functionality. This surely must have kindled your curiosity
to discover the rationale behind employing so many tags.
This is so, because each of
these tags, documents different features of the language. Let us assume that we
yearn for a bulleted list in our final documentation. We would have to use the
following tags to accomplish it:
a.cs
/// <list type="bullet">
/// <item>
/// <description>One</description>
/// </item>
/// <item>
/// <description>Two</description>
/// </item>
/// </list>
class zzz
{
public static void Main() {
}
}
xml fragment
<member name="T:zzz">
<list type="bullet">
<item>
<description>One</description>
</item>
<item>
<description>Two</description>
</item>
</list>
</member>
The attribute type can also be
assigned the values of bullet, number or table.
Bear in mind, that an external
program will interpret the XML tags. Thus, the designers of the language
standardized tags for describing different things. If the same tag had been
utilized for documenting every feature, a single program would have sufficed to
document the entire C# code. We have employed tags such as 'vijay' and 'mukhi'
to document our classes. Chaos would reign supreme, if everyone decided to use his
or her own names. Appended below is a brief summary of the various tags that
can be employed in the XML file:
• The param tag is used to document the parameters to a function.
• The paramref tag is used to document a parameter name.
• The permission tag is used to document the access allowed to a member.
• The remarks tag is used to specify the overall information for a class.
• The return tag has been introduced to document the return values of functions.
• The seealso tag helps in implementing the 'see also' section at the bottom of help sections.
• The summary tag documents all members of a type.
• The value tag documents all the properties.