En mi proyecto actual me he encontrado con el requisito de crear clases genéricas con el mismo nombre, pero con diferentes números de parámetros genéricos. Por ejemplo:
MyClass<T1>
MyClass<T1, T2>
MyClass<T1, T2, T3>
Dado que quiero todo esto en el mismo espacio de nombres, ¿estoy confundido sobre cómo estructurar y nombrar mis clases y archivos?
Si seguimos la idea de que deberíamos tener clases limitadas a una por archivo y que los archivos deberían estar en una estructura de carpetas que represente la jerarquía del espacio de nombres y que el nombre del archivo debería coincidir con el nombre de la clase, ¿cómo lidiar con esta situación? ?
Lo que realmente estoy pidiendo aquí es lo que debería nombrar el fichero que contiene MyClass<T1>
, y lo que debería nombrar el archivo que contiene MyClass<T1, T2>
? No estoy preguntando cuáles deberían ser los nombres de los parámetros de tipo.
TKey, TValue
convención. Func tiene unTResult
parámetro de tipo. Aunque estoy de acuerdo en que puede usarT1
,T2
etc. para un número variable de parámetros de entrada que de otra manera no tienen usos específicos comoTKey
yTValue
.Respuestas:
Y así sucesivamente, donde el número después del backtick es el número de parámetros de tipo genérico. Esta convención es utilizada por Microsoft.
Alternativamente, puedes usar algo como
que conserva no solo el número de parámetros de tipo genérico, sino también sus nombres específicos. Por supuesto, no conserva los corchetes angulares, pero no podemos tener todo lo que queremos en la vida, ¿verdad?
fuente
En el caso de
Tuple
yAction
que Pete ha mencionado, los propios Microsoft usan un solo archivo: consulte Tuple.cs y Action.cs .Creo que en parte depende de si la funcionalidad de todas las clases es básicamente la misma o no. Personalmente, no me gustan las clases agrupadas en un solo archivo, pero esto podría ser una excepción. En el código fuente donde trabajo, agregué una
NamedTuple
clase autogenerada (usando T4) que actúa de la misma maneraTuple
, pero con un nombre de cadena como primer argumento en el constructor.Para responder a su pregunta, si no desea usar un solo archivo, tal vez use MyClass_1.cs para
MyClass<T1>
, MyClass_2.cs paraMyClass<T1, T2>
, etc.Sin embargo, ninguna de las opciones es ideal, por lo que me inclinaría a sugerir el argumento "Microsoft hágalo de esta manera, así que ...".
fuente
Tuple
yAction
son todos delegados; no tienen ningún código de implementación, por lo que poner todas las variaciones en archivos separados sería un poco inútil de todos modos. Solo prueba que cada regla tiene una excepción.Tuple
no es un delegado, pero cada implementación es corta de todos modos.Func
.¿Te has preguntado si las clases realmente tienen la misma intención? Si una clase es más genérica que la otra, entonces será una GenericClass , una MoreGenericClass y una MostGenericClass . Imagine que cada parámetro de tipo de una clase agrega una nueva dimensión a la clase, por lo que puede ser útil preguntar qué dimensión es.
Tomemos este ejemplo:
Container<Thing>
MetricContainer<Thing, Metric>
MetricTransportableContainer<Thing, Metric, Transport>
Soy consciente de que no es el mejor ejemplo, pero es muy expresivo para mostrar tres dimensiones:
Para que pueda modelar el transporte de automóviles:
Transporte de fluidos:
Transporte de energía:
Transporte de azúcar, cereales:
Oh, qué sorpresa: a
List<T>
tiene una dimensión que representa las cosas que la lista puede contener; y esto esMap<T, S>
con dos dimensiones que representan las cosas que el mapa puede contener y las teclas de acceso.fuente
Tuple<T1>
,Tuple<T1, T2>
yTuple<T1, T2, T3>
en archivos CS separados de una manera estándar, sin conflictos de nombres?