Skip to content

BRO1617: Write a cref's type arguments in braces

A cref names a generic type or member with braces, cref="List{T}", not with escaped angle brackets, cref="List&lt;T&gt;". Checked in every cref attribute: <see>, <seealso>, <exception>, <inheritdoc> and any other element. Not a StyleCop rule: it's StyleCop's proposed SA1653 (#758), which the maintainers liked and nobody built.

Example

Before

using System.Collections.Generic;

/// <summary>Keeps a <see cref="List&lt;T&gt;"/> of names.</summary>
/// <seealso cref="Dictionary&lt;TKey, TValue&gt;"/>
public class Names
{
}

After

using System.Collections.Generic;

/// <summary>Keeps a <see cref="List{T}"/> of names.</summary>
/// <seealso cref="Dictionary{TKey, TValue}"/>
public class Names
{
}

Why

Both forms point at the same type, but List&lt;T&gt; is hard to read and to type, and a codebase that mixes the two can't be searched for one of them. Microsoft's documentation writes crefs with braces (cref="IDictionary{T, U}").

How the fix works

Each &lt; and &gt; that opens or closes a type argument (or type parameter) list becomes { or }; nothing else in the cref changes, so M&lt;T&gt;(List&lt;List&lt;T&gt;&gt;) becomes M{T}(List{List{T}}).

This rule reads documentation as XML, which the compiler only does when the project generates documentation (<GenerateDocumentationFile>true</GenerateDocumentationFile>), like the other documentation rules.

Not reported

  • Operators. cref="operator &lt;(C, C)": the &lt; is the operator, not a type argument list.
  • Crefs the compiler can't read (for example List&lt;int&gt;, which names a type argument instead of a type parameter): a person has to decide what they meant.
  • Escaped angle brackets in text (List&lt;T&gt; outside a cref) and anything inside <code>.