¿Cuál es la mejor manera de estructurar y nombrar archivos que contienen clases genéricas con el mismo nombre?

14

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.

Stephen
fuente
Danos algunos ejemplos específicos que describan el problema con más detalle. Los ejemplos que ha proporcionado son también ... erm, genéricos. ¿Qué quiere decir con "cómo estructurar y nombrar mis clases y archivos?"
Robert Harvey
Microsoft lo hace solo agregando un número al parámetro de tipo. Vea los documentos de Tuple: msdn.microsoft.com/en-us/library/…
Pete
@Pete: Eso solo se aplica a Tuple. Microsoft también usa la TKey, TValueconvención. Func tiene un TResultparámetro de tipo. Aunque estoy de acuerdo en que puede usar T1, T2etc. para un número variable de parámetros de entrada que de otra manera no tienen usos específicos como TKeyy TValue.
Robert Harvey
@RobertHarvey Bueno, sí, pero solo en el contexto de una colección de clave / valor real, como un diccionario. Para cualquier cosa que consista en un número variable de tipos, agregan un número. Aquí hay otro ejemplo: msdn.microsoft.com/en-us/library/dd402872(v=vs.110).aspx
Pete
1
Bueno, tus ediciones obsoletas algunos de los comentarios. :) ¿Por qué no puedes mantener las clases en el mismo archivo físico? Si son tan diferentes que necesita guardarlos en archivos separados, ¿puede decirnos qué los hace diferentes?
Pete

Respuestas:

14
MyGenericClass`1.cs
MyGenericClass`2.cs
MyGenericClass`3.cs

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

MyGenericCollectionClass[TKey, TValue].cs

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?

Robert Harvey
fuente
1
El compilador internamente manipula el nombre de los tipos genéricos, agregando un backtick y el número de parámetros genéricos, ya que .NET no permite múltiples tipos con el mismo nombre con un número diferente de parámetros genéricos, pero C # sí. Entonces, la convención de nomenclatura de archivos coincide con lo que hace el compilador.
CodesInChaos
1
Quería demostrar que estás equivocado, pero en realidad tienes razón: github.com/dotnet/corefx/tree/master/src/… No me gusta esta convención.
Den
1
@ Den, parece que ahora se han arrepentido de esa convención. Tal vez implicaba algún problema? github.com/dotnet/corefx/commit/…
Sam
@Sam Con suerte, no es un problema de comunicación entre los equipos de Microsoft. Porque nadie más lo está haciendo. También depende del equipo del compilador, no del equipo de la biblioteca, decidir en mi opinión.
Den
No tendría las bolas para usar "` "en un nombre de archivo.
Cristian E.
4

En el caso de Tupley Actionque 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 NamedTupleclase autogenerada (usando T4) que actúa de la misma manera Tuple, 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 para MyClass<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 ...".

Wai Ha Lee
fuente
2
Tupley Actionson 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.
Robert Harvey
Sí, en términos generales, poner varios delegados públicos en el mismo archivo se considera correcto (siempre que estén relacionados).
Stephen
1
@RobertHarvey, Tupleno es un delegado, pero cada implementación es corta de todos modos.
Arturo Torres Sánchez
@ ArturoTorresSánchez: Correcto, estaba pensando Func.
Robert Harvey
0

¿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:

  • Dimensión interna, lo que puede cargar
  • Dimensión métrica, con qué métrica se puede cargar, solo por conteo de cosas o por medida cuadrada o por capacidad cúbica o por peso
  • Dimensión exterior, donde se puede cargar.

Para que pueda modelar el transporte de automóviles:

Container<Cars>
MetricContainer<Cars, CountMetric>
MetricTransportableContainer<Cars, CountMetric, Ship>

Transporte de fluidos:

Container<Fluid>
MetricContainer<Fluid, Volume>
MetricTransportableContainer<Fluid, Volume, Shelf>

Transporte de energía:

Container<Energy>
MetricContainer<Energy, ElectricPower>
MetricTransportableContainer<Energy, ElectricPower, Box>

Transporte de azúcar, cereales:

Container<CrumblyMaterial>
MetricContainer<CrumblyMaterial, Weight>
MetricTransportableContainer<CrumblyMaterial, Weight, Silo>

Oh, qué sorpresa: a List<T>tiene una dimensión que representa las cosas que la lista puede contener; y esto es Map<T, S>con dos dimensiones que representan las cosas que el mapa puede contener y las teclas de acceso.

shylynx
fuente
1
No creo que hayas entendido la pregunta. Mira el último párrafo de la pregunta.
Robert Harvey
1
@RobertHarvey Lea atentamente la pregunta: classname debe ser equivalente al nombre del archivo. Es indistintamente. El problema radica en un análisis incorrecto de la clase y un nombre incorrecto de las clases genéricas en general. Para resumir mi respuesta: "nómbrelo como es y no como parece ser".
shylynx
1
@RobertHarvey Lea mi respuesta: ¡Ponga una clase en un archivo!
shylynx
1
Creo que te estás perdiendo el punto. La pregunta es: ¿cómo pongo Tuple<T1>, Tuple<T1, T2>y Tuple<T1, T2, T3>en archivos CS separados de una manera estándar, sin conflictos de nombres?
Robert Harvey