Как ссылаться на общие классы и методы в документации XML

При написании XML-документации вы можете использовать <see cref="something">something</see>, который работает конечно. Но как вы ссылаетесь на класс или метод с универсальными типами?

public class FancyClass<T>
{
  public string FancyMethod<K>(T value) { return "something fancy"; }
}

Если бы я собирался написать где-нибудь документацию xml, как бы я сослался на причудливый класс? как я могу сослаться на FancyClass<string>? Как насчет метода?

Например, в другом классе я хотел, чтобы пользователь знал, что я верну экземпляр FancyClass<int>, Как я могу сделать что-нибудь для этого?

8 ответов

Решение

Для ссылки на метод:

/// <see cref="FancyClass{T}.FancyMethod{K}(T)"/> for more information.

TL; DR:

"Как бы я сослался FancyClass<T> ?"

   /// <see cref="FancyClass{T}"/>

"Как насчет FancyClass<T>.FancyMethod<K>(T value) ?"

   /// <see cref="FancyClass{T}.FancyMethod{K}(T)"/>

"Как я могу сослаться на FancyClass<string> ?"

   /// <see cref="SomeType.SomeMethod(FancyClass{string})"/>
   /// <see cref="FancyClass{T}"/> whose generic type argument is <see cref="string"/>

Пока вы можете ссылаться на метод, чья подпись включает FancyClass<string> (например, как тип параметра), вы не можете ссылаться на такой закрытый универсальный тип напрямую. Второй пример работает вокруг этого ограничения. (Это видно, например, на странице MSDN Refence для статического System.String.Concat(IEnumerable<string>) метод).:

XML документация комментарий cref правила:

  • Окружить список параметров универсального типа фигурными скобками {} вместо с <> угловые скобки. Это избавит вас от побега последнего как &lt; а также &gt; - помните, комментарии к документации в формате XML!

  • Если вы включите префикс (например, T: для типов, M: для методов, P: для свойств, F: для полей), компилятор не будет выполнять проверку ссылки, а просто скопирует cref Значение атрибута прямо в документацию XML. По этой причине вам придется использовать специальный синтаксис "строка идентификатора", который применяется в таких файлах: всегда использовать полностью определенные идентификаторы и использовать обратные ссылки для ссылки на параметры универсального типа (`n по типам, ``n по методам).

  • Если вы пропустите префикс, применяются обычные правила именования языков: вы можете отбросить пространства имен, для которых есть using заявление, и вы можете использовать ключевые слова типа языка, такие как int вместо System.Int32, Также компилятор проверит ссылку на правильность.

XML документация комментарий cref шпаргалка:

namespace X
{
    using System;

    /// <see cref="I1"/>  (or <see cref="X.I1"/> from outside X)
    /// <see cref="T:X.I1"/>
    interface I1
    {
        /// <see cref="I1.M1(int)"/>  (or <see cref="M1(int)"/> from inside I1)
        /// <see cref="M:X.I1.M1(System.Int32)"/>
        void M1(int p);

        /// <see cref="I1.M2{U}(U)"/>
        /// <see cref="M:X.I1.M2``1(``0)"/>
        void M2<U>(U p);

        /// <see cref="I1.M3(Action{string})"/>
        /// <see cref="M:X.I1.M3(System.Action{System.String})"/>
        void M3(Action<string> p);
    }

    /// <see cref="I2{T}"/>
    /// <see cref="T:X.I2`1"/>
    interface I2<T>
    {
        /// <see cref="I2{T}.M1(int)"/>
        /// <see cref="M:X.I2`1.M1(System.Int32)"/>
        void M1(int p);

        /// <see cref="I2{T}.M2(T)"/>
        /// <see cref="M:X.I2`1.M2(`0)"/>
        void M2(T p);

        /// <see cref="I2{T}.M3{U}(U)"/>
        /// <see cref="M:X.I2`1.M3``1(``0)"/>
        void M3<U>(U p);
    }
}
/// <summary>Uses a <see cref="FancyClass{T}" /> instance.</summary>

Кстати, он присутствовал в документации MSDN .Net Framework 2.0 и 3.0, но исчез в версии 3.5

Ни один из приведенных ответов не работает для меня полностью. ReSharper не будет преобразовывать тег see в ссылку, поддерживающую Ctrl+ click (например, ), если это полностью не решает.

Если метод в OP был в пространстве имен, называется Testполностью разрешенная ссылка на показанный метод будет выглядеть так:

<see cref="M:Test.FancyClass`1.FancyMethod``1(`0)"/>

Как вы можете выяснить, перед числом параметров типа класса должен быть только один обратный тик, затем два обратных тика перед числом параметров типа метода, тогда параметры являются индексированным параметром с нулевым индексом и соответствующим количеством обратных токов.

Итак, мы можем видеть, что FancyClass имеет один параметр типа класса, FancyMethod имеет один тип параметра и объект FancyClass Тип параметра будет передан методу.

Как вы можете видеть более ясно в этом примере:

namespace Test
{
    public class FancyClass<A, B>
    {
        public void FancyMethod<C, D, E>(A a, B b, C c, D d, E e) { }
    }
}

Ссылка становится:

M:Test.FancyClass`2.FancyMethod``3(`0,`1,``0,``1,``2)

Или "Класс с двумя параметрами типа, который имеет метод с тремя параметрами типа, где параметры метода ClassType1, ClassType2, MethodType1, MethodType2, MethodType3"


Как дополнительное примечание, я нигде не нашел этого документированного, и я не гений, компилятор сказал мне все это. Все, что вам нужно сделать, это создать тестовый проект, включить документацию XML, затем вставить код, для которого вы хотите разработать ссылку, и поставить начало комментария к документу XML (///):

namespace Test
{
    public class FancyClass<T>
    {
        ///
        public string FancyMethod<K>(T value) { return "something fancy"; }
    }

    public class Test
    {
        public static void Main(string[] args) { }
    }
}

Затем создайте свой проект, и выходная документация XML содержит ссылку в doc->members->member элемент под атрибутом name:

<?xml version="1.0"?>
<doc>
    <assembly>
        <name>Test</name>
    </assembly>
    <members>
        <member name="M:Test.FancyClass`1.FancyMethod``1(`0)">

        </member>
    </members>
</doc>

Далее из ответов Лассе и TBC:

/// <see cref="T:FancyClass`1{T}"/> for more information.

/// <see cref="M:FancyClass`1{T}.FancyMethod`1{K}(T)"/> for more information.

также будет правильно отображать всплывающие подсказки, тогда как их версия отображает фигурные скобки.

/// Here we discuss the use of <typeparamref name="TYourExcellentType"/>.
/// <typeparam name="TYourExcellentType">Your exellent documentation</typeparam>

Вот ответ, который я дал где-то еще. Это также будет работать для классов и методов.

Я перепробовал все на переполнении стека, чтобы получить результаты, которые работают в нескольких сценариях. Вот решение, которое мне подходит. (Это субъективно по отношению ко всем остальным.)

  1. Создает интерактивные ссылки.
  2. Наведение указателя на идентификаторы работает.
  3. Правильно создает файл .xml.
  4. Не вызывает ошибок в intellisense.
  5. Работает с параметрами универсального типа, допускающими значение NULL.
  6. Работает в Resharper и имеет встроенное окно XML Doc (Resharper -> Edit -> Show Quick Documentation)
  7. Работает в предварительной версии XAM Doc для расширения Atomineer Pro Documentaion Visual Studio.
  8. Работает с универсальным типом универсального типа.

Пример # 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.

Пример №2 (с использованием "Т")

        /// <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!;
/// <see cref="FancyClass&lt;T>.FancyMethod&lt;K>(T)"/> for more information.
Другие вопросы по тегам