Referring to a generic type of a generic type in C# XML documentation?
Asked Answered
H

7

49

Writing some XML documentation for a predicate helper class. But I can't figure out I can refer to an Expression<Func<T, bool>> without getting a syntax error. Is it even possible? I have tried this:

<see cref="Expression{Func{T, bool}}"/>

But I get a red squiggly line under {T, bool}}. This works though:

<see cref="Expression{TDelegate}"/>

Anyone have a clue?


Update:

The answer that was given (and I accepted) seemingly did work. But now I have started to get a lot of warnings about stuff not being able to resolve. I have a class called ExpressionBuilder<T> which works with Expression<Func<T, bool>> a lot. So I of course want to refer to that in my XML comments.

I have tried both versions that I know about:

<see cref="Expression&lt;Func&lt;T, Boolean&gt;&gt;"/>
<see cref="Expression{Func{T, Boolean}}"/>

But neither work. (And on the last one, ReSharper puts a blue squiggly under {T,Boolean}} I get two warnings under compilation everywhere I have used it which says that:

  1. XML comment on 'blah blah' has cref attribute 'Expression>' that could not be resolved
  2. Type parameter declaration must be an identifier not a type. See also error CS0081.

Have the same issue somewhere I tried to refer to Range<Nullable<DateTime>> (Range<DateTime?> didnt work either. Both with { } and with &lt; &gt;)

Am I not supposed to refer to these kinds of generics?

Hairbreadth answered 26/3, 2009 at 8:55 Comment(3)
I was about to ask the same question. It took me a while to find this one because the title isn't very keyword-y. Can I suggest, "How do I refer to a generic type of a generic type in C# XML documentation"? You might also add the "generics" tag. I don't have the rep to do it myself.Hames
<see cref="Expression{Func{T, Boolean}}"/> works fine in VS2015, Reshaper 9Parous
The message says "Type parameter declaration must be an identifier not a type"; for example, if you have List{Int32}, it should be, List{T} because there's not an actual List{Int32} class sitting around in the code base somewhere, there's only a List{T}. Int32 is a type, T is an identifier.Lengthwise
H
50

There seems to be no way to refer to a generic of a generic in XML documentation, because actually, there's no way to refer to a generic of any specific type.

Lasse V Karlsen's answer made it click for me:

If you write <see cref="IEnumerable{Int32}" />, the compiler just uses "Int32" as the type parameter name, not the type argument. Writing <see cref="IEnumerable{HelloWorld}" /> would work just as well. This makes sense because there is no specific page in MSDN for "IEnumerable of int" that your documentation could link to.

To document your class properly, I think you'd have to write something like:

<summary>
Returns an <see cref="IEnumerable{T}" /> of <see cref="KeyValuePair{T,U}" /> 
of <see cref="String" />, <see cref="Int32" />.
</summary>

I hope you like text.

Hames answered 10/6, 2009 at 21:17 Comment(2)
No I hate text, that's why I asked this question. Oh well... maybe in a future version of xml-doc :pHairbreadth
Unfortunately, nothing has changed in 2020, and this still seems to be the only real solution. Still can't reference generic types like Nullable<int> in cref XML comments.Krug
H
12

What exactly would you like it to link to?

There's no such thing in the documentation as a Expression<Func<T>>, so obviously a link to that would not work.

You can link to Expression<TDelegate> because that exists.

As for what works or not, neither of the following works in Visual Studio 2008 / .NET 3.5 for me:

/// <see cref="Expression&lt;Func&lt;T&gt;&gt;"/>.
/// <see cref="Expression{Func{T}}"/>.

But this works:

/// <see cref="Expression{T}"/>.

so apparently the generic type parameter doesn't have to the same as the one in the declaration.

Hambrick answered 28/4, 2009 at 11:13 Comment(2)
So there is no way of refering to a generic type with a spesific type argument? Like if I had a function that returned a List<Func<T, bool>>, I would only be able to say that it returned a List<T>?Hairbreadth
That is because "String" is then just used as the generic type name. Try List<DOOBIEDOOBIEDOO> and it'll work just as great.Hambrick
G
4

Don't use an empty see element (<see cref="..." />). Instead, put text inside the see element

<see cref="IEnumerable{T}">IEnumerable</see>&lt;<see cref="..."/>&gt;
Garb answered 6/12, 2017 at 23:12 Comment(1)
Exactly what I was looking for. Can you fix the typo? Just replace $gt; by &gt;Amalgamation
D
3
// Use "&lt;" instead of "<" symbol and "&gt;" instead of ">" symbol.

// Sample:

<see cref="Expression&lt;Func&lt;T, bool&gt;&gt;"/>
Dour answered 26/3, 2009 at 9:0 Comment(5)
Oh my... that is ugly... but it does work =/ Why does it accept the { } for one type but not more, kind of?Hairbreadth
Sure about what? Like I said, I get no red squiggly line when using Expression{TDelegate} or for example List{String}. Actually, when I write <see and press enter, it auto completes to <see cref=""/>. When I then write List and press enter, it autocompletes to List{T}.Hairbreadth
Note that the red squiggly line is not Visual Studio, most likely ReSharper or Refactor! Pro, and they are sometimes confused as well. Trust the compiler.Hambrick
Visual studio 2010 is flagging stuff like this with a warning. Apparently MS felt that not doing so in 2008 was a bug.Grobe
No need for &gt;, this is well-formed XML: <see cref="Expression&lt;Func&lt;T, bool>>"/>Mcloughlin
H
1

I'm running into this now, as I have a function that returns a List<List<byte>>. Yeah, it's ugly, but I didn't write it. Standard disclaimer, I know.

Anyway, in VS 2017 with R# Ultimate 2017.1, this doc comment...

<returns><see cref="List{List{Byte}}" /> of split frames</returns>

...gives me a syntax error. However, this...

<returns><see><cref>List{List{byte}}</cref></see> of split frames</returns>

...does not. Eeeenteresting.

Still ugly? Yes.

As ugly? I think it's less horrible than using &lt; and &gt; myself....

Harms answered 2/6, 2017 at 14:34 Comment(0)
B
0

I tried everything on stack overflow to a get results that work under several scenarios. Here's a solution that works for me. (That's subjective concerning anyone else.)

  1. Produces clickable links.
  2. Hovering over identifiers works.
  3. Produces .xml file correctly.
  4. Produces no errors in intellisense.
  5. Works for nullable generic type parameters.
  6. Works in Resharper and it's built-in XML Doc window (Resharper -> Edit -> Show Quick Documentation)
  7. Works in XAM Doc Preview for Atomineer Pro Documentaion Visual Studio Extension.
  8. Works with a generic type of a generic type.

Example #1

  /// <summary>
  ///  This instance field holds a reference to the
  ///  <see cref="ConcurrentDictionary{Decimal, Boolean}"/> as
  ///  <see cref="T:ConcurrentDictionary&lt;decimal, bool?&gt;"/> that contains
  ///  the list of all PDF's that are currently opened and being displayed.
  /// </summary>
  private ConcurrentDictionary<decimal, bool?> openedPdfs = default!;

  Note: 
    The ConcurrentDictionary{Decimal, Boolean} will correctly produce a
    clickable link of ConcurrentDictionary{TKey, TValue} on hovering while
    T:ConcurrentDictionary&lt;decimal, bool?&gt; makes sure the reader gets
    information on what type TKey and TValue are.

Example # 2 (using "T")

  /// <summary>
  ///  This instance field holds a reference to the
  ///  <see cref="ConcurrentDictionary{TKey, TValue}"/> as
  ///  <see cref="T:ConcurrentDictionary&lt;decimal, bool?&gt;"/> that contains
  ///  the list of all PDF's that are currently opened and being displayed.
  /// </summary>
  private ConcurrentDictionary<decimal, bool?> openedPdfs = default!;
Bowers answered 12/3, 2021 at 21:44 Comment(0)
T
0

I came to use this:

<see cref=""EqualityComparer{T}.Default"">EqualityComparer&lt;<typeparamref name=""TSource""/>&gt;.Default</see>

Applied to your OP here the result:

<see cref="System.Linq.Expressions.Expression{TDelegate}">Expression&lt;Func&lt;<typeparamref name="TSource"/>, Boolean&gt;&gt;.</see>

Here the image of the IntelliSense pop-up:

Render of the comment in VS2019

Tenantry answered 11/11, 2021 at 20:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.