Qu'est-ce qu'une bonne convention de dénomination pour les types génériques en C #? [fermé]

16

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 Tdoit toujours être un type de fruit, tel que Appleou Orange. Le type Tdoit 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?

void.pointer
la source
3
Ce n'est pas une question constructive. Il n'obtiendra des réponses qu'avec le style préféré de l'affiche.
Michael K
1
Jetez un œil aux contraintes, en considérant votre exemple: msdn.microsoft.com/en-us/library/d5x73970.aspx#Y426
Matthieu
2
@Michael, il y aura un certain nombre de réponses, et la réponse acceptée sera la préférée de Robert, mais diverses autres réponses seront votées.
StuperUser
5
@Michael Une question subjective obtient une réponse subjective. La question est toujours constructive car elle sert de point de référence pour quiconque souhaite une variété d'idées / solutions à ce problème particulier. Celui que je marque comme réponse ne représente pas la seule et unique information utile.
void.pointer
Peut-être le transformer en un wiki communautaire, comme une bonne ressource, bien que subjective,?
tylermac

Réponses:

22

C'est en effet subjectif ... ish .
Comme certains trouvent que ic'est parfaitement valable pour une variable de boucle for, certains pensent que Tc'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

public class Dictionary<TKey, TValue>

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.

public class Tuple<T1, T2, T3>
Binaire Worrier
la source
2
Je ne trouve pas cela subjectif du tout. iet le Ttravail, 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.
Konrad Rudolph
2
@ Konon: Vous avez raison. . . Cependant, la question n'est pas étiquetée comme subjective, le demandeur admet qu'il s'agit d'un sujet subjectif en supposant que les gens ont tendance à avoir leurs propres préférences sur les conventions de dénomination. Donc, bien que la question ne soit pas subjective (et en fait ce n'est pas le cas, car il existe une réponse correcte, c'est-à-dire la réponse qui renvoie à la directive officielle de Microsoft), le sujet est subjectif, car je suis sûr que quelqu'un publiera un " iet Tsont diaboliques . Il ne faut jamais utiliser de noms à une seule lettre". J'ai ajouté un ish pour aider à satisfaire tout le monde :)
Binary Worrier
1
Je pense que les commentaires ajoutés à eux seuls en font une réponse très précieuse, bien que la réponse elle-même soit très utile. Test logique lorsque nous parlons d'un type sans contraintes, TFruitest 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!!
void.pointer
1
Juste pour noter, cela s'aligne avec les directives de conception du .NET Framework pour les développeurs de bibliothèques de MSDN. Voir: Noms des paramètres de type générique .
Grant Thomas
7

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

class Juice<TFruit> where TFruit...

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.

class SomeAlgorithm<TypeT> where TypeT : Type

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.

Faucon
la source
L'utilisation du Tpréfixe pour les paramètres de type et Ipour les noms d'interface est explicitement requise ( règles " DO ...") dans les directives de conception du cadre.
Richard
1
On peut se demander ce que l'utilisation TFruitici apporte à la table T. Utiliser un nom tel que TTypeor TypeTest certainement absurde. Il n'ajoute aucune information sur juste T. Les mêmes informations exactes sont transmises.
Konrad Rudolph
@Konrad Rudolph: Regardez attentivement mon exemple de TypeT, il couvre un cas particulier lorsque vous traitez avec System.Type. Je pense que mes noms ont une entropie plus élevée que l'utilisation de T pour le type, surtout si le générique est également contraint.
Falcon
7

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:

Nommez les paramètres de type générique avec des noms descriptifs, à moins qu'un nom à une seule lettre ne soit complètement explicite et qu'un nom descriptif n'ajoute pas de valeur.

IDictionary<TKey, TValue> 

est un exemple d'une interface qui suit cette directive.

Envisagez d'utiliser la lettre T comme nom de paramètre de type pour les types avec un paramètre de type à une seule lettre.

Faites préfixer les noms de paramètres de type descriptif avec la lettre T.

Pensez à indiquer les contraintes placées sur un paramètre de type dans le nom du paramètre. Par exemple, un paramètre contraint à ISession peut être appelé TSession.

Matthieu
la source
Une meilleure référence serait le livre Framework Design Guidelines ou le (résumé) sur MSDN, notamment les noms des classes, des structures et des interfaces .
Richard
@Richard: ajusté ma réponse en tenant compte de votre commentaire, merci!
Matthieu
2

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 Tenglobe 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 Tet S(ou Qquoi que ce soit) serait moins utile que de les appeler, disons, KeyTypeet ValueType, ou TKeyet TVal.

tdammers
la source
1

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 Tindépendamment de ce qui suit, tout comme les interfaces sont généralement préfacées I.

  • 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. TInet TOut, 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 Uou V. 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 Tet la suivante TParam, à moins que la deuxième classe ne soit imbriquée dans la première rendant Tindisponible pour une utilisation dans la seconde.

KeithS
la source