O que é uma boa convenção de nomenclatura para tipos genéricos em c #? [fechadas]

16

Eu decidi fazer esta pergunta aqui em vez de no estouro de pilha, porque é bastante subjetivo.

Em C #, normalmente vejo tipos genéricos com nomes muito ruins. Especificamente, "T" é comumente usado, mas não é um nome significativo por si só. Por exemplo:

class Fruit<T>
{
    T fruit;
}

Embora essa seja a abordagem típica, alguém recomendaria contra isso? E se sim, qual seria uma convenção de nomenclatura razoável para tipos genéricos no contexto de C # para funções e classes genéricas?

No meu exemplo anterior, vamos supor que o tipo genérico Tsempre deve ser um tipo de fruta, como Appleor Orange. O tipo Tprecisa deixar óbvio que é um tipo de fruta, então talvez seja um nome melhor FruitType, então terminamos com:

class Fruit<FruitType>
{
    FruitType fruit;
}

Isso é apenas para dar uma idéia do que estou procurando. O que é uma "regra de ouro" aceitável para esse problema?

void.pointer
fonte
3
Esta não é uma pergunta construtiva. Só receberá respostas com o estilo favorito do pôster.
Michael K
1
Ter um olhar para as restrições, considerando o seu exemplo: msdn.microsoft.com/en-us/library/d5x73970.aspx#Y426
Matthieu
2
@ Michael, haverá várias respostas, e a resposta aceita será a favorita de Robert, mas várias outras respostas serão votadas.
StuperUser
5
@ Michael Uma pergunta subjetiva recebe uma resposta subjetiva. A questão ainda é construtiva porque serve como ponto de referência para quem deseja uma variedade de idéias / soluções para esse problema em particular. O que eu marquei como resposta não representa a única e única informação útil.
void.pointer
Talvez transformá-lo em um wiki da comunidade, como um recurso bom, embora subjetivo?
tylermac

Respostas:

22

É realmente subjetivo ... ish .
Como algumas pessoas acham que ié perfeitamente válido para uma variável de loop for, alguns acham que Té perfeitamente válido para um espaço reservado de tipo em uma classe genérica.

Pessoalmente, defendo essa abordagem, é uma convenção comum e as pessoas geralmente sabem o que você quer dizer.

Onde o tipo é significativo, eu usaria um nome significativo, mas geralmente o inicio com T. Desenvolvi recentemente uma classe de dicionário genérica (não pergunte) e a declaração foi

public class Dictionary<TKey, TValue>

No entanto, para algo como uma tupla, onde os tipos são essencialmente sem sentido, considero o seguinte perfeitamente aceitável.

public class Tuple<T1, T2, T3>
Preocupação binária
fonte
2
Eu não acho isso subjetivo. ie Ttrabalho, e isso é mensurável em princípio (ou seja, é mensurável se a compreensão do código-fonte aumenta se, digamos, os índices de loop obtiverem identificadores diferentes). Só porque é difícil de medir, não significa que precisamos marcar o rótulo "subjetivo" em tudo. Dado o amplo uso sem problemas óbvios, é bastante razoável dizer, mesmo sem medir que isso realmente funciona.
Konrad Rudolph
2
@ Konrad: Você tem razão. . . no entanto, a pergunta não é marcada como subjetiva, o autor da pergunta admite que é um tópico subjetivo, supondo que as pessoas tendem a ter suas próprias preferências em convenções de nomenclatura. Portanto, embora a pergunta possa não ser subjetiva (e, na verdade, não é porque existe uma resposta correta, ou seja, a resposta que vincula a diretriz oficial da Microsoft), o tópico é subjetivo, pois tenho certeza que alguém publicará uma " ie Tsão maus . Nunca se deve usar nomes de letras únicas", responda. Adicionou um ish a ajuda satisify everyone :)
Binary Worrier
1
Penso que apenas os comentários adicionados a este post o tornam uma resposta muito valiosa, embora a resposta em si seja muito útil. Tfaz sentido quando estamos falando de um tipo sem restrições, TFruitfaz sentido porque me diz "Qualquer tipo com a restrição de que é uma fruta". Parece uma boa "regra de ouro" para nomear parâmetros de tipo genérico. Obrigado!!
void.pointer
1
Apenas para observar, isso está alinhado às Diretrizes de design do .NET Framework para desenvolvedores de bibliotecas do MSDN. Consulte: Nomes de parâmetros de tipo genérico .
Grant Thomas
7

Acho que você está certo, embora T tenha se tornado um padrão. Provavelmente se origina dos tempos antigos em C ++ e da redação "do tipo T". Considero uma boa prática ser o mais descritivo possível, mas isso é subjetivo.

Você pode escolher T como prefixo, assim como muitas pessoas escolhem I para interfaces. portanto

class Juice<TFruit> where TFruit...

seria um bom nome na minha humilde opinião. Prefiro prefixos a sufixos na maioria dos casos, pois fica imediatamente claro o que você está vendo quando o encontra e é mais fácil procurar por coisas como o Intellisense. Também é uma boa prática para os controles da interface do usuário, quando você provavelmente sempre conhece o tipo (por exemplo, TextBox), mas não tem 100% de certeza sobre o nome descritivo que deu a ele.

O lado negativo disso é que fica ruim quando o tipo começa com T. Então, acho que seria bom sufocar o tipo genérico em casos especiais, como o abaixo.

class SomeAlgorithm<TypeT> where TypeT : Type

Por favor, note que esta é apenas a minha opinião e altamente subjetiva. Mas acho que tenho um argumento menor ao preferir o prefixo ao sufixo.

Falcão
fonte
O uso de Tprefixo para parâmetros de tipo e Inomes de interface é explicitamente necessário ( regras " DO ...") nas Diretrizes de Design da Estrutura.
21411 Richard
1
É questionável o que usar TFruitaqui traz para a mesa T. Usar nomes como TTypeou TypeTcertamente é um absurdo. Não adiciona nenhuma informação sobre apenas T. A mesma informação exata é transmitida.
Konrad Rudolph
@ Konrad Rudolph: Olhe atentamente para o meu exemplo de TypeT, que abrange um caso especial ao lidar com System.Type. Eu acho que meus nomes têm uma entropia mais alta do que apenas usar T para o tipo, especialmente se o genérico também estiver restrito.
Falcon
7

A Microsoft possui uma diretriz oficial sobre genéricos: nomes de classes, estruturas e interfaces (citados aqui e em formato de livro: diretrizes de design da estrutura ).

Em relação à sua pergunta específica, ela diz:

Nomeie parâmetros de tipo genérico com nomes descritivos, a menos que um nome de uma letra seja completamente auto-explicativo e um nome descritivo não agregue valor.

IDictionary<TKey, TValue> 

é um exemplo de uma interface que segue esta diretriz.

Considere usar a letra T como o nome do parâmetro de tipo para tipos com um parâmetro de tipo de letra única.

Prefixe os nomes dos parâmetros do tipo descritivo com a letra T.

Considere indicar restrições colocadas em um parâmetro de tipo no nome do parâmetro. Por exemplo, um parâmetro restrito a ISession pode ser chamado de TSession.

Matthieu
fonte
Uma referência melhor seria o livro Framework Design Guidelines ou o (resumo) no MSDN, principalmente nomes de classes, estruturas e interfaces .
21411 Richard
@ Richard: ajustou minha resposta considerando seu comentário, obrigado!
Matthieu
2

O objetivo dos genéricos é delegar funcionalidade - a classe genérica faz uma coisa, seu argumento faz outra. O exemplo do livro é uma coleção genérica: a coleção armazena 'coisas', mas não se importa com o que são essas coisas. Um nome genérico (sic!), Portanto, tem uma certa lógica - não queremos que seja descritivo, porque não há nada a descrever além de "é o argumento de tipo genérico", que o nome Tabrange exaustivamente (considerando a Convenção). Ser descritivo é bom, mas ser excessivamente descritivo sugere restrições que não existem.

Às vezes, no entanto, uma classe ou método genérico possui mais de um parâmetro de tipo e, nesse ponto, faz sentido fornecer nomes mais descritivos, para que seu papel se torne óbvio. Um bom exemplo seria para um tipo de coleção de valores-chave, onde chave e valor são genéricos; chamá-los Te S(ou Qqualquer outra coisa) seria menos útil do que chamá-los, digamos, KeyTypee ValueType, ou TKeye TVal.

tdammers
fonte
1

A resposta é realmente subjetiva. No entanto, ele tem mérito como questão, pois o código deve se auto-documentar, e todos nós poderíamos aprender maneiras melhores de fazê-lo.

A seguir estão as convenções que aprendi e sigo:

  • Os parâmetros do tipo genérico nunca devem ser confundidos com classes concretas. Isso geralmente incentiva um prefácio, Tindependentemente do que se segue, bem como as interfaces geralmente são precedidas I.

  • Um único parâmetro de tipo genérico em uma classe ou método geralmente deve ser rotulado T. Esta é uma convenção quase universalmente compreendida, que remonta aos modelos C ++.

  • Vários parâmetros de tipo genérico na mesma classe ou declaração de método devem começar com T, mas ser diferenciados por alguns meios concisos, mas compreensíveis. TIne TOut, por exemplo, são GTPs comuns e bem compreendidos para um método que aceita uma entrada genérica fortemente tipada e produz uma saída genérica fortemente tipada.

  • Vários tipos diferenciados, mas não dignos de nota, como para uma classe que contenha como Tupla da .Net ou tipos de delegado como Func, Predicate e Action, podem ser rotulados como T1, T2, T3 etc. No entanto, declarações GTP "notáveis" / ou restrições de tipos muito específicos) devem ter algo mais descritivo.

  • Um único tipo genérico em um método, que difere do tipo genérico de uma classe que contém, pode seguir a regra anterior referente a vários tipos em uma classe ou método, OU se o tipo não for digno de nota, exceto ser diferente, pode receber uma letra única, frequentemente Uou V. Esta é novamente uma convenção que remonta aos modelos C ++.

  • O que você escolher, mantenha-o consistente; não rotule um GTP para uma classe Te a seguinte TParam, a menos que a segunda classe esteja aninhada na primeira, tornando Tindisponível para uso na segunda.

KeithS
fonte