Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference operators in XML documentation

I would like to reference an operator in a <see cref="..." /> XML documentation tag, but I can't seem to find any hints on how to do it. The MSDN article on this tag only shows a simple example referencing a method, but does not go over different types of members that can be referenced.

In particular, I would like to reference an implicit conversion operator, but general rule for referencing operators will also be appreciated.


Example

Let's say we have a simple structure for which we define ==, != and implicit conversion operators:

public struct MyStructure
{
    public int Value { get; set; }

    public static bool operator ==(MyStructure x, MyStructure y) => x.Value == y.Value;

    public static bool operator !=(MyStructure x, MyStructure y) => x.Value != y.Value;

    public static implicit operator MyStructure(int i) => new MyStructure { Value = i };
}

Simply enough one can reference the Value property with <see cref="MyStructure.Value" />, but how to go about referencing the == operator? I obviously tried <see cref="MyStructure.==" /> and <see cref="MyStructure.==(MyStructure, MyStructure)" /> but I don't think this works as it should because of these two observations:

  1. The operator is not coloured in the tooltip showing a summary as opposed to other members being coloured when properly referenced
  2. The Go to definition command does not work whereas it does for other properly referenced members

I also suspect tools like Sandcastle used to generate HTML pages based on the XML documentation would not produce valid hyperlinks either, but that remains to be confirmed.

EDIT

I just confirmed that Sandcastle does not produce valid hyperlinks for any of my attempts. Also, when the option to generate the XML documentation in the project properties is checked, a warning with code CS1584 is shown saying "XML comment has syntactically incorrect cref attribute 'MyStructure.=='".


Justification

In case someone is wondering why do I want to reference an operator the answer is I am writing a unit test method performing tests on an operator and as a general rule I put references to tested members in the XML documentation for the test method. So what I'm after is this:

/// <summary>
/// This method performs tests regarding <see cref="..." /> operator
/// </summary>
[TestMethod]
public void ImplicitConversionOperator() { ... }
like image 723
Grx70 Avatar asked Nov 18 '16 11:11

Grx70


People also ask

What is XML documentation in C#?

XML Documentation helps other programmers or developers to use your code (classes, functions and their members) easily by providing some useful information. XML Documentation starts with three slashes before the class or function to be documented.

How do I create an XML document in Visual Studio?

From the menu bar, choose Tools > Options to open the Options dialog box. Then, navigate to Text Editor > C# (or Visual Basic) > Advanced. In the Editor Help section, look for the Generate XML documentation comments option.

How do you comment a method in C#?

In C#, there are 3 types of comments: Single Line Comments ( // ) Multi Line Comments ( /* */ ) XML Comments ( /// )


2 Answers

To elaborate on @Clay's answer - there are two ways (that I know of) of referencing operators in the <see (...)/> XML documentation tag:

1. Using generated method names

See this question for reference.

For the equality operator bool operator ==(MyStructure x, MyStructure y) the reference is

<see cref="MyStructure.op_Equality(MyStructure, MyStructure)" />

For the implicit conversion operator implicit operator MyStructure(int i) it is

<see cref="MyStructure.op_Implicit(int)" />

There is however a drawback to this approach (as far as I can tell). For conversion operators the method names are op_Implicit and op_Explicit for implicit and explicit operators respectively. It is possible to have several overloads of these methods differing only by the return type. For instance, for these two operators:

public static implicit operator int(MyStructure s) => s.Value;
public static implicit operator double(MyStructure s) => s.Value;

these methods will be generated:

int op_Implicit(MyStructure)
double op_Implicit(MyStructure)

Then this reference:

<see cref="MyStructure.op_Implicit(MyStructure)" />

will be ambiguous, and it will fallback to whichever operator is defined first. You'll also get a warning saying just that.

2. Using C# operator names

For the equality operator bool operator ==(MyStructure x, MyStructure y) the reference is

<see cref="MyStructure.operator ==(MyStructure, MyStructure)" />

and for the implicit conversion operator implicit operator MyStructure(int i):

<see cref="MyStructure.implicit operator MyStructure(int)" />

Obviously there's no problem in disambiguating previously mentioned example:

<see cref="MyStructure.implicit operator int(MyStructure)" />
<see cref="MyStructure.implicit operator double(MyStructure)" />

Other considerations

One other difference that I've noticed is that the second approach is properly recognized by CodeLens, whereas the first one is not.

like image 54
Grx70 Avatar answered Oct 17 '22 03:10

Grx70


I'm on VS 2015 Enterprise...dunno 'bout other editions. It looks like, if you document your operator, you get full-on correct behavior:

/// <summary>The name sez it all</summary>
public struct MyStruct
{
  /// <summary>implicit</summary>
  /// <param name="i">an int</param>
  public static implicit operator MyStruct( int i )
  {
    return new MyStruct( );
  }
  /// <summary>Thus and so</summary>
  public static bool operator ==( MyStruct a, MyStruct b )
  {
    return false;
  }

  /// <summary>Thus and so</summary>
  public static bool operator !=( MyStruct a, MyStruct b )
  {
    return true;
  }

  /// <summary>Thus and so</summary>
  public override bool Equals( object obj )
  {
    return base.Equals( obj );
  }

  /// <summary>Thus and so</summary>
  public override int GetHashCode( )
  {
    return base.GetHashCode( );
  }

  /// <summary>Thus and so</summary>
  public override string ToString( )
  {
    return base.ToString( );
  }
}

Then, to reference, this works and lights up with all the IDE functionality (except that it doesn't show in the member drop-down):

/// <summary>
/// See <see cref="MyStruct.operator=="/>
/// </summary>
[StructLayout( LayoutKind.Sequential )]
internal struct BY_HANDLE_FILE_INFORMATION
{
   //...
}

Go-to functionality works here, too.

Edit:

Implicit operator is:

<see cref="MyStruct.op_Implicit(int)"
like image 7
Clay Avatar answered Oct 17 '22 01:10

Clay