Como referenciar classes e métodos genéricos na documentação xml

198

Ao escrever a documentação xml, você pode usar <see cref="something">something</see>, o que funciona, é claro. Mas como você faz referência a uma classe ou a um método com tipos genéricos?

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

Se eu fosse escrever uma documentação xml em algum lugar, como referenciaria a classe sofisticada? como posso fazer referência a FancyClass<string>? E o método?

Por exemplo, em uma classe diferente, eu queria informar ao usuário que retornarei uma instância de FancyClass<int>. Como eu poderia fazer uma coisa de ver cref por isso?

Svish
fonte

Respostas:

257

Para referenciar o método:

/// <see cref="FancyClass{T}.FancyMethod{K}(T)"/> for more information.
Lasse V. Karlsen
fonte
3
Obrigado por essa resposta! É realmente faltando página do MSDN em <ver>: msdn.microsoft.com/en-us/library/acd0tfbe.aspx
joce
6
Na verdade, acredito que ele também funcione nas dicas do VS2010, você precisa indicar o número de argumentos genéricos, por exemplo "FancyClass 1{T}.FancyMethod1 {K} (T)"
Stephen Drew
Não sei o que você quer dizer sobre isso. Eu nunca tive que adicioná-los, e sempre funcionou para mim. Você tem um exemplo específico em que não funciona? Em caso afirmativo, por favor, publique-o em algum lugar (ou até mesmo forneça uma resposta).
Lasse V. Karlsen
@Lasse, veja a resposta e os comentários de Steve abaixo. Sua resposta não cobre as dicas corretas do Intellisense.
Jakub Januszkiewicz
43
/// <summary>Uses a <see cref="FancyClass{T}" /> instance.</summary>

BTW, ele estava presente na documentação do MSDN do .Net Framework 2.0 e 3.0 , mas desapareceu na versão 3.5

thinkbeforecoding
fonte
4
e quanto a uma instância específica de T? gosta de corda? Talvez não seja possível?
Svish
O que você quer dizer? Você não pode declarar uma versão específica, portanto também não pode se referir a ela.
Lasse V. Karlsen
Se um método, por exemplo, retornar apenas List <string>, por exemplo. Mas não é importante :)
Svish
7
Sim, eu estava pensando também ... os resharpers rabiscam ao escrever FancyClass {string}, mas não ao escrever FancyClass {String} ...
thinkbeforecoding
6
A razão para a observação acima de "Think Before Coding" é que ela não funciona com os aliases de c #. Por exemplo, você precisa usar Int32, em vez de int, Singleem vez de floatetc. (Colocar esta informação aqui no caso de alguém tropeça mais neste)
AnorZaken
27

TL; DR:

"Como eu faria referência FancyClass<T>?"

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

"Sobre o quê FancyClass<T>.FancyMethod<K>(T value)?"

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

"Como posso referenciar a FancyClass<string>?"

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

Embora você possa fazer referência a um método cuja assinatura inclua FancyClass<string>(por exemplo, como um tipo de parâmetro), não é possível fazer referência diretamente a um tipo genérico fechado. O segundo exemplo contorna essa limitação. (Isso é visto, por exemplo, na página de referênciaSystem.String.Concat(IEnumerable<string>) do MSDN para o método estático ). :

crefRegras de comentários da documentação XML :

  • Coloque a lista de parâmetros de tipo genérico entre chaves, em{} vez de entre <>colchetes. Isso evita que você escape deste último &lt;e &gt;lembre-se de que os comentários da documentação são XML!

  • Se você incluir um prefixo (comoT: para tipos, M:métodos, P:propriedades, F:campos), o compilador não executará nenhuma validação da referência, mas simplesmente copiará o crefvalor do atributo diretamente para a saída XML da documentação. Por esse motivo, você precisará usar a sintaxe especial "ID string" que se aplica a esses arquivos: sempre use identificadores totalmente qualificados e use backticks para referenciar parâmetros de tipo genérico ( `nem tipos, ``nem métodos).

  • Se você omitir o prefixo , aplicar-se-ão regras regulares de nomeação de idiomas: você pode eliminar os namespaces para os quais há umusing instrução e pode usar as palavras-chave do tipo de idioma, como em intvez de System.Int32. Além disso, o compilador irá verificar a referência para correção.

crefFolha de dicas sobre comentários da documentação XML :

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);
    }
}
stakx - não está mais contribuindo
fonte
Como referenciar apenas a Tparte?
Nawfal # 10/18
4
Descobri:<typeparamref name="T"/>
nawfal 10/10
21

Nenhuma das respostas mostradas até agora funciona completamente para mim. O ReSharper não converterá a tag see em um Ctrllink com + clique (por exemplo imagem aqui), a menos que seja completamente resolvida.

Se o método no OP estivesse em um namespace chamado Test, o link completamente resolvido para o método mostrado seria:

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

Como você pode resolver, deve haver apenas um backtick antes do número de parâmetros do tipo de classe, depois dois backticks antes do número de parâmetros do tipo de método e, em seguida, os parâmetros são o parâmetro indexado a zero com o número apropriado de backticks.

Portanto, podemos ver que FancyClasspossui um parâmetro de tipo de classe, FancyMethodtem um parâmetro de tipo e um objeto do FancyClasstipo de parâmetro será passado para o método

Como você pode ver mais claramente neste exemplo:

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

O link se torna:

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

Ou "Classe com dois parâmetros de tipo que tem um método com três parâmetros do tipo em que os parâmetros do método são ClassType1, ClassType2, MethodType1, MethodType2,MethodType3 "


Como uma observação adicional, não encontrei isso documentado em nenhum lugar e não sou um gênio, o compilador me contou tudo isso. Tudo o que você precisa fazer é criar um projeto de teste, ativar a documentação XML , inserir o código para o qual deseja criar um link e colocar o início de um comentário de documento 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) { }
    }
}

Em seguida, construa seu projeto e a documentação XML gerada inclui o link no elemento doc-> members-> membersob o atributo name:

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

        </member>
    </members>
</doc>
MrLore
fonte
3
Isso deve receber mais votos positivos, principalmente por causa do truque para encontrar a notação correta, sem ter que passar por tentativa e erro. Kudos meu homem
Peter
10

Além das respostas de Lasse e TBC:

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

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

também fornecerá dicas de ferramenta corretamente, enquanto sua versão a renderiza com chaves.

Stephen Drew
fonte
2
Usando <ver CREF = "System.Collections.Generic.List 1{T}"/>** causes a build-time warning: **XML comment on 'Blah' has syntactically incorrect cref attribute 'System.Collections.Generic.List1 <T> - Gostaria de elaborar sobre como se deve usar isso?
Jakub Januszkiewicz
2
Oi Jakub, Isso realmente não parece funcionar. A única maneira de obter dicas de ferramentas para funcionar corretamente é <ver cref = "T: <fullTypeName>` 1 {T} "/>.
Stephen Drew
2
OK, entendi parcialmente. Se o método em si não for genérico (como na Lista <T> .Add ()), isso funcionará: <consulte cref = "M: System.Collections.Generic.List`1 {T} .Add (T)" /> .
Jakub Januszkiewicz
1
Não parece estar funcionando para mim. Eu tenho <see cref = "M: System.Collections.Generic.List`1 {T}" /> no cabeçalho do comentário para um método de extensão genérico que eu escrevi (converte um ArrayList em uma Lista <T>), mas o ReSharper o sinaliza como sendo um erro de sintaxe, e o IntelliSense apenas o exibe literalmente. VS 2010 / R # 6.1.37.86
Mike Loux
8
Aha! Consegui fazer com que <see cref = "T: System.Collections.Generic.List`1" /> " funcionasse. Então, usar T: em vez de chaves, fez o truque. Ele expande o espaço de nome completo, e o truque não funcionará se você não incluir o espaço para nome, portanto não é perfeito, mas funcionará
Mike Loux
5
/// Here we discuss the use of <typeparamref name="TYourExcellentType"/>.
/// <typeparam name="TYourExcellentType">Your exellent documentation</typeparam>
JohnL4
fonte
3
Observe que as outras respostas abrangem como referenciar uma classe genérica; esta resposta mostra como referenciar o parâmetro type por conta própria, que era o que eu estava procurando fazer.
JRH
1
/// <see cref="FancyClass&lt;T>.FancyMethod&lt;K>(T)"/> for more information.
Max Toro
fonte