In meinem aktuellen Projekt bin ich auf die Anforderung gestoßen, generische Klassen mit demselben Namen, aber unterschiedlicher Anzahl von generischen Parametern zu erstellen. Beispielsweise:
MyClass<T1>
MyClass<T1, T2>
MyClass<T1, T2, T3>
Da ich alle im selben Namespace haben möchte, bin ich nicht sicher, wie ich meine Klassen und Dateien strukturieren und benennen soll.
Wenn wir der Idee folgen, dass wir Klassen auf eine pro Datei beschränken sollten und dass sich Dateien in einer Ordnerstruktur befinden sollten, die die Namespace-Hierarchie darstellt, und dass der Name der Datei mit dem Namen der Klasse übereinstimmen sollte, wie gehe ich mit dieser Situation um ?
Was ich hier wirklich frage, ist, wie soll ich die Datei benennen, die enthält MyClass<T1>
, und wie soll ich die Datei benennen, die enthält MyClass<T1, T2>
? Ich frage nicht, wie die Namen der Typparameter sein sollten.
TKey, TValue
Konvention. Func hat einenTResult
Typparameter. Obwohl ich damit einverstanden , dass Sie verwenden könnenT1
,T2
usw. für eine variable Anzahl von Eingabeparametern , die wie keine sonst spezifische Anwendungen habenTKey
undTValue
.Antworten:
Und so weiter, wobei die Zahl nach dem Backtick die Anzahl der generischen Typparameter ist. Diese Konvention wird von Microsoft verwendet.
Alternativ können Sie auch so etwas verwenden
Dabei bleibt nicht nur die Anzahl der generischen Typparameter erhalten, sondern auch deren spezifische Namen. Zugegeben, es bewahrt nicht die spitzen Klammern, aber wir können nicht alles im Leben haben, was wir wollen, oder?
quelle
Im Fall von
Tuple
undAction
, die Pete erwähnt hat, verwendet Microsoft selbst eine einzige Datei - siehe Tuple.cs und Action.cs .Ich denke, es hängt zum Teil davon ab, ob die Funktionalität für alle Klassen grundsätzlich gleich ist oder nicht. Ich persönlich mag es nicht, Klassen in einer einzelnen Datei zusammenzufassen, aber dies könnte eine Ausnahme sein. In dem Quellcode, in dem ich arbeite, habe ich eine automatisch generierte
NamedTuple
Klasse (unter Verwendung von T4) hinzugefügt, die genauso funktioniert wieTuple
, aber einen String-Namen als erstes Argument in den Konstruktor einfügt.Um Ihre Frage zu beantworten, wenn Sie keine einzige Datei verwenden möchten
MyClass<T1>
, verwenden Sie möglicherweise MyClass_1.cs für , MyClass_2.cs fürMyClass<T1, T2>
usw.Keine der beiden Optionen ist jedoch ideal, weshalb ich das Argument "Microsoft macht es so, also ..." vorschlagen möchte.
quelle
Tuple
undAction
sind alle Delegierten; Sie haben keinen Implementierungscode, daher wäre es irgendwie sinnlos, alle Variationen in separate Dateien zu packen. Beweist nur, dass jede Regel eine Ausnahme hat.Tuple
ist kein Delegierter, aber jede Implementierung ist trotzdem kurz.Func
.Hast du dich gefragt, ob die Klassen wirklich die gleiche Absicht haben? Wenn eine Klasse generischer als die andere ist, handelt es sich um eine GenericClass , eine MoreGenericClass und eine MostGenericClass . Stellen Sie sich vor, jeder Typparameter einer Klasse fügt der Klasse eine neue Dimension hinzu. Daher kann es hilfreich sein, zu fragen, um welche Dimension es sich handelt.
Nehmen wir dieses Beispiel:
Container<Thing>
MetricContainer<Thing, Metric>
MetricTransportableContainer<Thing, Metric, Transport>
Mir ist bewusst, dass es nicht das beste Beispiel ist, aber es ist sehr aussagekräftig, drei Dimensionen zu zeigen:
So können Sie den Transport von Autos modellieren:
Transport von Flüssigkeiten:
Transport von Energie:
Transport von Zucker, Getreide:
Oh, was für eine Überraschung: a
List<T>
hat eine Dimension, die die Dinge repräsentiert, die die Liste enthalten kann; und dies ist eineMap<T, S>
zweidimensionale Karte, die die Dinge darstellt, die die Karte enthalten kann, und die Zugriffstasten.quelle
Tuple<T1>
,Tuple<T1, T2>
undTuple<T1, T2, T3>
in separate CS - Dateien in einem Standardverfahren , ohne Namenskonflikte?