J'ai décidé de poser cette question ici au lieu du débordement de pile car c'est plutôt subjectif.
En C #, je vois généralement des types génériques avec des noms très pauvres. Plus précisément, "T" est couramment utilisé mais n'est pas un nom significatif en soi. Par exemple:
class Fruit<T>
{
T fruit;
}
Bien qu'il s'agisse de l'approche typique, quelqu'un recommanderait-il contre cela? Et si oui, quelle serait une convention de dénomination raisonnable pour les types génériques dans le contexte de C # pour les fonctions et classes génériques?
Dans mon exemple précédent, supposons que le type générique T
doit toujours être un type de fruit, tel que Apple
ou Orange
. Le type T
doit rendre évident qu'il s'agit d'un type de fruit, alors peut-être qu'un meilleur nom serait FruitType
, alors nous nous retrouvons avec:
class Fruit<FruitType>
{
FruitType fruit;
}
C'est juste pour vous donner une idée de ce que je recherche. Quelle est la «règle d'or» acceptable pour ce problème?
Réponses:
C'est en effet subjectif ... ish .
Comme certains trouvent que
i
c'est parfaitement valable pour une variable de boucle for, certains pensent queT
c'est parfaitement valide pour un espace réservé de type dans une classe générique.J'épouse personnellement cette approche, c'est une convention commune et les gens savent généralement ce que vous voulez dire.
Lorsque le type est significatif, j'utiliserais un nom significatif, mais je commencerais généralement par T. J'ai récemment développé une classe de dictionnaire générique (ne demandez pas) et la déclaration était
Cependant, pour quelque chose comme un Tuple, où les types sont essentiellement dénués de sens, je considère ce qui suit parfaitement acceptable.
la source
i
et leT
travail, et cela est mesurable en principe (c'est-à-dire qu'il est mesurable si la compréhension du code source augmente si, par exemple, les indices de boucle obtiennent des identifiants différents). Ce n'est pas parce qu'il est difficile à mesurer que nous devons étiqueter l'étiquette «subjective» sur tout. Compte tenu de la large utilisation sans problèmes évidents, il est tout à fait raisonnable de dire même sans mesurer que cela fonctionne en fait.i
etT
sont diaboliques . Il ne faut jamais utiliser de noms à une seule lettre". J'ai ajouté un ish pour aider à satisfaire tout le monde :)T
est logique lorsque nous parlons d'un type sans contraintes,TFruit
est logique car il me dit "Tout type avec la contrainte que c'est un fruit". Cela semble être une bonne "règle générale" pour nommer les paramètres de type générique. Merci!!Je pense que vous avez raison, bien que T soit devenu une norme. Il provient probablement des anciens temps C ++ et du libellé "de type T". Je considère que c'est une bonne pratique d'être aussi descriptive que possible, mais c'est subjectif.
Vous pouvez choisir T comme préfixe, tout comme beaucoup de gens choisissent I pour les interfaces. Donc
serait un bon nom à mon humble avis. Je préfère les préfixes aux suffixes dans la plupart des cas, car il est immédiatement clair ce que vous voyez lorsque vous tombez dessus et il est plus facile de rechercher avec des choses comme Intellisense. C'est également une bonne pratique pour les contrôles UI, lorsque vous connaissez très probablement toujours le type (par exemple TextBox) mais n'êtes pas sûr à 100% du nom descriptif que vous lui avez donné.
Le côté négatif est qu'il semble mauvais quand le type lui-même commence par T. Donc je pense que ce serait une bonne chose de suffixer le type générique dans des cas spéciaux, comme celui ci-dessous.
Veuillez noter que c'est juste mon avis et très subjectif. Mais je pense que j'ai un petit point à préférer le préfixe au suffixe.
la source
T
préfixe pour les paramètres de type etI
pour les noms d'interface est explicitement requise ( règles " DO ...") dans les directives de conception du cadre.TFruit
ici apporte à la tableT
. Utiliser un nom tel queTType
orTypeT
est certainement absurde. Il n'ajoute aucune information sur justeT
. Les mêmes informations exactes sont transmises.Microsoft a une directive officielle concernant les génériques: noms de classes, structures et interfaces (cités ici et sous forme de livre: Framework Design Guidelines ).
Concernant votre question spécifique, il dit:
la source
L'intérêt des génériques est de déléguer des fonctionnalités - la classe générique fait une chose, son argument en fait une autre. L'exemple de manuel est une collection générique: la collection stocke des «choses», mais peu importe ce que sont ces choses. Un nom générique (sic!) A donc une certaine logique - nous ne voulons pas qu'il soit descriptif, car il n'y a rien d'autre à décrire que "c'est l'argument de type générique", que le nom
T
englobe de manière exhaustive (considérant la Convention). Être descriptif, c'est bien, mais être trop descriptif suggère des restrictions qui n'existent pas.Parfois, cependant, une classe ou une méthode générique a plus d'un paramètre de type, et à ce stade, il est logique de leur donner des noms plus descriptifs, afin que leur rôle devienne évident. Un bon exemple serait pour un type de collection clé-valeur, où clé et valeur sont génériques; les appeler
T
etS
(ouQ
quoi que ce soit) serait moins utile que de les appeler, disons,KeyType
etValueType
, ouTKey
etTVal
.la source
La réponse est en effet subjective. Cependant, cela a du mérite en tant que question, car le code devrait s'auto-documenter, et nous pourrions peut-être tous apprendre de meilleures façons de le faire.
Voici les conventions que j'ai apprises et respectées:
Les paramètres de type générique ne devraient jamais pouvoir être confondus avec des classes concrètes. Cela encourage généralement une préface
T
indépendamment de ce qui suit, tout comme les interfaces sont généralement préfacéesI
.Un seul paramètre de type générique sur une classe ou une méthode doit généralement être étiqueté
T
. Il s'agit d'une convention presque universellement connue qui remonte aux modèles C ++.Plusieurs paramètres de type générique sur la même déclaration de classe ou de méthode doivent tous commencer par T, mais être différenciés par des moyens concis mais compréhensibles.
TIn
etTOut
, par exemple, sont des GTP courants et bien compris pour une méthode qui accepte une entrée générique fortement typée et produit une sortie générique fortement typée.Plusieurs types différenciés mais non marquants, comme pour une classe conteneur comme le tuple de .Net ou des types délégués comme Func, Predicate et Action, peuvent être étiquetés T1, T2, T3, etc. Cependant, des déclarations GTP "remarquables" (ayant un but précis et / ou restrictions de type très spécifiques) devraient avoir quelque chose de plus descriptif.
Un seul type générique sur une méthode, qui diffère du type générique d'une classe contenant, peut soit suivre la règle précédente concernant plusieurs types dans une classe ou une méthode, OU si le type est banal autre que d'être différent, il peut être donné un autre lettre unique, souvent
U
ouV
. C'est encore une convention qui remonte aux modèles C ++.Quoi que vous choisissiez de faire, restez cohérent; N'étiquetez pas un GTP pour une classe
T
et la suivanteTParam
, à moins que la deuxième classe ne soit imbriquée dans la première rendantT
indisponible pour une utilisation dans la seconde.la source