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 T
sempre deve ser um tipo de fruta, como Apple
or Orange
. O tipo T
precisa 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?
Respostas:
É realmente subjetivo ... ish .
Como algumas pessoas acham que
i
é perfeitamente válido para uma variável de loop for, alguns acham queT
é 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
No entanto, para algo como uma tupla, onde os tipos são essencialmente sem sentido, considero o seguinte perfeitamente aceitável.
fonte
i
eT
trabalho, 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.i
eT
são maus . Nunca se deve usar nomes de letras únicas", responda. Adicionou um ish a ajuda satisify everyone :)T
faz sentido quando estamos falando de um tipo sem restrições,TFruit
faz 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!!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
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.
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.
fonte
T
prefixo para parâmetros de tipo eI
nomes de interface é explicitamente necessário ( regras " DO ...") nas Diretrizes de Design da Estrutura.TFruit
aqui traz para a mesaT
. Usar nomes comoTType
ouTypeT
certamente é um absurdo. Não adiciona nenhuma informação sobre apenasT
. A mesma informação exata é transmitida.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:
fonte
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
T
abrange 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
T
eS
(ouQ
qualquer outra coisa) seria menos útil do que chamá-los, digamos,KeyType
eValueType
, ouTKey
eTVal
.fonte
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,
T
independentemente do que se segue, bem como as interfaces geralmente são precedidasI
.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.
TIn
eTOut
, 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
U
ouV
. 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
T
e a seguinteTParam
, a menos que a segunda classe esteja aninhada na primeira, tornandoT
indisponível para uso na segunda.fonte