Ich habe mich dazu entschlossen, diese Frage hier zu stellen, anstatt auf Stapelüberlauf, da sie eher subjektiv ist.
In C # sehe ich normalerweise generische Typen mit sehr schlechten Namen. Insbesondere wird "T" häufig verwendet, ist jedoch für sich genommen kein aussagekräftiger Name. Beispielsweise:
class Fruit<T>
{
T fruit;
}
Während dies der typische Ansatz ist, würde jemand dagegen empfehlen? Und wenn ja, was wäre eine sinnvolle Namenskonvention für generische Typen im Kontext von C # für generische Funktionen und Klassen?
Nehmen wir in meinem vorherigen Beispiel an, dass der generische Typ T
immer ein Obsttyp wie Apple
oder sein muss Orange
. Der Typ T
muss deutlich machen, dass es sich um eine Obstsorte handelt. Ein besserer Name wäre also FruitType
:
class Fruit<FruitType>
{
FruitType fruit;
}
Dies ist nur, um euch eine Vorstellung davon zu geben, wonach ich suche. Was ist eine akzeptable Faustregel für dieses Problem?
Antworten:
Es ist in der Tat subjektiv ... ish .
Einige Leute finden
i
, dass dies für eine for-Schleifenvariable durchaus gilt, andere denken, dass diesT
für einen Typplatzhalter in einer generischen Klasse durchaus gilt.Ich persönlich unterstütze diesen Ansatz, es ist eine übliche Konvention und die Leute wissen im Allgemeinen , was Sie meinen.
Wo der Typ aussagekräftig ist, verwende ich einen aussagekräftigen Namen, aber beginne ihn im Allgemeinen mit T. Vor kurzem habe ich eine generische Dictionary-Klasse entwickelt (fragen Sie nicht), und die Deklaration war
Für etwas wie ein Tupel, bei dem die Typen im Wesentlichen bedeutungslos sind, halte ich jedoch Folgendes für vollkommen akzeptabel.
quelle
i
undT
Arbeit, und dies ist im Prinzip messbar (dh es ist messbar, ob das Verständnis des Quellcodes zunimmt, wenn beispielsweise Schleifenindizes unterschiedliche Bezeichner erhalten). Nur weil es schwer zu messen ist, heißt das nicht, dass wir das „subjektive“ Etikett auf allem markieren müssen. Angesichts des breiten Einsatzes ohne offensichtliche Probleme ist es durchaus sinnvoll zu sagen, auch ohne zu messen, dass dies tatsächlich funktioniert.i
undT
sind böse . Man darf niemals einzelne Buchstaben verwenden", tippe answer. Habe ein ish hinzugefügt , um alle zufriedenzustellen :)T
Sinnvoll, wenn es sich um einen Typ ohne Einschränkungen handelt. Sinnvoll,TFruit
weil er zu mir sagt: "Jeder Typ mit der Einschränkung, dass es sich um eine Frucht handelt." Dies scheint eine gute "Faustregel" für die Benennung generischer Typparameter zu sein. Vielen Dank!!Ich denke, Sie haben Recht, obwohl T ein ziemlicher Standard geworden ist. Es stammt wahrscheinlich aus der alten C ++ - Zeit und dem Wortlaut "vom Typ T". Ich halte es für eine gute Praxis, so beschreibend wie möglich zu sein, aber das ist subjektiv.
Sie könnten T als Präfix wählen, ähnlich wie viele Leute I für Schnittstellen wählen. Somit
wäre meiner bescheidenen meinung nach ein guter name. Ich bevorzuge Präfixe gegenüber Suffixen in den meisten Fällen, da sofort klar ist, was Sie sehen, wenn Sie darauf stoßen, und es einfacher ist, mit Dingen wie Intellisense zu suchen. Dies ist auch für Benutzeroberflächen-Steuerelemente eine gute Praxis, wenn Sie den Typ (z. B. TextBox) mit hoher Wahrscheinlichkeit immer kennen, sich aber nicht hundertprozentig sicher sind, welchen beschreibenden Namen Sie ihm gegeben haben.
Das Negative daran ist, dass es schlecht aussieht, wenn der Typ selbst mit T beginnt. Ich halte es also für eine gute Sache, den generischen Typ in besonderen Fällen wie dem folgenden anzufügen.
Bitte beachten Sie, dass dies nur meine Meinung und sehr subjektiv ist. Aber ich glaube, ich habe ein kleines Problem damit, Präfixe den Suffixen vorzuziehen.
quelle
T
Präfixes für Typparameter undI
für Schnittstellennamen ist in den Framework Design Guidelines ausdrücklich erforderlich (" DO ..." - Regeln).TFruit
hier auf den Tisch bringtT
. Verwenden von Namen wieTType
oderTypeT
ist sicherlich Unsinn. Es fügt einfach keinerlei Informationen hinzuT
. Genau die gleichen Informationen werden übermittelt.Microsoft hat eine offizielle Richtlinie in Bezug auf Generika: Namen von Klassen, Strukturen und Schnittstellen ( hier und in Buchform: Framework Design Guidelines ).
In Bezug auf Ihre spezifische Frage heißt es:
quelle
Der springende Punkt bei Generika ist, Funktionalität zu delegieren - die generische Klasse macht eine Sache, ihr Argument macht eine andere. Das Lehrbuchbeispiel ist eine generische Sammlung: Die Sammlung speichert "Dinge", aber es ist egal, was diese Dinge sind. Ein generischer Name (sic!) Hat also eine gewisse Logik - wir wollen nicht, dass er beschreibend ist, denn es gibt nichts anderes zu beschreiben als "es ist das generische Typargument", das der Name
T
ausführlich umfasst (wenn man bedenkt) Das Treffen). Beschreibend zu sein ist gut, aber zu beschreibend zu sein deutet auf Einschränkungen hin, die es nicht gibt.Manchmal hat eine generische Klasse oder Methode jedoch mehr als einen Typparameter, und an dieser Stelle ist es sinnvoll, ihnen aussagekräftigere Namen zu geben, damit ihre Rolle offensichtlich wird. Ein gutes Beispiel wäre ein Auflistungstyp für Schlüsselwerte, bei dem sowohl Schlüssel als auch Wert generisch sind. Sie anzurufen
T
undS
(oderQ
was auch immer) wäre weniger nützlich als sie anzurufen, sagen wir,KeyType
undValueType
, oderTKey
undTVal
.quelle
Die Antwort ist in der Tat subjektiv. Es ist jedoch eine wichtige Frage, da sich Code selbst dokumentieren sollte, und wir könnten möglicherweise alle lernen, wie man es besser macht.
Das Folgende sind die Konventionen, die ich gelernt habe und die ich befolge:
Generische Typparameter sollten niemals mit konkreten Klassen verwechselt werden können. Dies fördert im Allgemeinen ein Vorwort,
T
unabhängig davon, was folgt, ähnlich wie Schnittstellen im Allgemeinen vorangestellt werdenI
.Ein einzelner generischer Typparameter für eine Klasse oder Methode sollte in der Regel gekennzeichnet werden
T
. Dies ist eine nahezu universelle Konvention, die auf C ++ - Vorlagen zurückgeht.Mehrere generische Typparameter in derselben Klassen- oder Methodendeklaration sollten alle mit T beginnen, sich jedoch durch einige prägnante, aber verständliche Mittel unterscheiden.
TIn
undTOut
zum Beispiel sind gängige und gut verstandene GTPs für eine Methode, die eine stark typisierte generische Eingabe akzeptiert und eine stark typisierte generische Ausgabe erzeugt.Mehrere differenzierte, aber unauffällige Typen, z. B. für eine übergeordnete Klasse wie .Net's Tuple oder Delegate-Typen wie Func, Predicate und Action, können als T1, T2, T3 usw. bezeichnet werden. "Bemerkenswerte" GTP-Deklarationen (mit einem bestimmten Zweck und / oder sehr spezifische Typeinschränkungen) sollten etwas aussagekräftigeres haben.
Ein einzelner generischer Typ in einer Methode, der sich vom generischen Typ einer enthaltenden Klasse unterscheidet, kann entweder der vorherigen Regel in Bezug auf mehrere Typen in einer Klasse oder Methode folgen, ODER wenn der Typ nicht auffällig ist, sondern sich unterscheidet, kann ihm ein anderer Typ zugewiesen werden einzelner Buchstabe, oft
U
oderV
. Dies ist wieder eine Konvention, die auf C ++ - Vorlagen zurückgeht.Was auch immer Sie tun, halten Sie es konsistent; Beschriften Sie ein GTP nicht für eine
T
und die nächste Klasse , esTParam
sei denn, die zweite Klasse ist in der ersten verschachtelt und kann in der zweitenT
nicht verwendet werden.quelle