¿Qué es una buena convención de nomenclatura para tipos genéricos en C #? [cerrado]

16

Decidí hacer esta pregunta aquí en lugar del desbordamiento de la pila porque es bastante subjetivo.

En C #, típicamente veo tipos genéricos con nombres muy pobres. Específicamente, "T" se usa comúnmente, pero no es un nombre significativo en sí mismo. Por ejemplo:

class Fruit<T>
{
    T fruit;
}

Si bien este es el enfoque típico, ¿alguien recomendaría no hacerlo? Y si es así, ¿cuál sería una convención de nomenclatura razonable para tipos genéricos en el contexto de C # para funciones y clases genéricas?

En mi ejemplo anterior, supongamos que el tipo genérico Tsiempre debe ser un tipo de fruta, como Appleo Orange. El tipo Tdebe hacer obvio que es un tipo de fruta, por lo que quizás sea un nombre mejor FruitType, por lo que terminamos con:

class Fruit<FruitType>
{
    FruitType fruit;
}

Esto es solo para darles una idea de lo que estoy buscando. ¿Qué es una "regla de oro" aceptable para este problema?

void.pointer
fuente
3
Esta no es una pregunta constructiva. Solo obtendrá respuestas con el estilo favorito del afiche.
Michael K
1
Eche un vistazo a las restricciones, considerando su ejemplo: msdn.microsoft.com/en-us/library/d5x73970.aspx#Y426
Matthieu
2
@Michael habrá varias respuestas, y la respuesta aceptada será la favorita de Robert, pero se votarán varias otras respuestas.
StuperUser
55
@Michael Una pregunta subjetiva obtiene una respuesta subjetiva. La pregunta sigue siendo constructiva porque sirve como punto de referencia para cualquiera que desee una variedad de ideas / soluciones a este problema en particular. El que marco como respuesta no representa el único bit de información útil.
void.pointer
¿Quizás convertirlo en una wiki comunitaria, como un buen recurso, aunque subjetivo?
tylermac

Respuestas:

22

De hecho es subjetivo ... ish .
Como algunas personas encuentran que ies perfectamente válido para una variable de bucle for, algunos piensan que Tes perfectamente válido para un marcador de posición de tipo en una clase genérica.

Personalmente, defiendo este enfoque, es una convención común y la gente generalmente sabe a qué te refieres.

Cuando el tipo es significativo, usaría un nombre significativo, pero generalmente lo comienzo con T. Recientemente desarrollé una clase de diccionario genérico (no pregunte) y la declaración fue

public class Dictionary<TKey, TValue>

Sin embargo, para algo como una Tupla, donde los tipos son esencialmente sin sentido, considero que lo siguiente es perfectamente aceptable.

public class Tuple<T1, T2, T3>
Binario Worrier
fuente
2
No encuentro esto subjetivo en absoluto. iy Ttrabajo, y esto es medible en principio (es decir, es medible si la comprensión del código fuente aumenta si, por ejemplo, los índices de bucle obtienen identificadores diferentes). El hecho de que sea difícil de medir no significa que tengamos que etiquetar la etiqueta "subjetiva" en todo. Dado el amplio uso sin problemas obvios, es bastante razonable decir incluso sin medir que esto realmente funciona.
Konrad Rudolph el
2
@ Konrad: Tienes un punto. . . Sin embargo, la pregunta no está etiquetada como subjetiva, el autor de la pregunta admite que es un tema subjetivo, suponiendo que la gente tiende a tener sus propias preferencias sobre las convenciones de nomenclatura. Entonces, aunque la pregunta puede no ser subjetiva (y de hecho no lo es, ya que hay una respuesta correcta, es decir, la respuesta que se vincula con la directriz oficial de Microsoft) el tema es subjetivo, ya que estoy seguro de que alguien publicará un " iy Tson malvados . Uno nunca debe usar nombres de una sola letra", escriba la respuesta. He agregado un ish para ayudar a satisfacer a todos :)
Binary Worrier
1
Creo que solo los comentarios agregados a esta publicación hacen que sea una respuesta muy valiosa, aunque la respuesta en sí es muy útil. Ttiene sentido cuando hablamos de un tipo sin restricciones, TFruittiene sentido porque me dice "Cualquier tipo con la restricción de que es una fruta". Esto parece una buena "regla general" para nombrar parámetros de tipo genérico. ¡¡Gracias!!
void.pointer
1
Solo para tener en cuenta, esto se alinea con las Pautas de diseño de .NET Framework para desarrolladores de bibliotecas de MSDN. Ver: Nombres de parámetros de tipo genérico .
Grant Thomas el
7

Creo que tienes razón, aunque T se ha convertido en un estándar. Probablemente se origina en los viejos tiempos de C ++ y la redacción "de tipo T". Considero que es una buena práctica ser lo más descriptivo posible, pero eso es subjetivo.

Puede elegir T como prefijo, al igual que muchas personas eligen I para las interfaces. Así

class Juice<TFruit> where TFruit...

Sería un buen nombre en mi humilde opinión. Prefiero los prefijos a los sufijos en la mayoría de los casos, ya que está claro de inmediato lo que estás viendo cuando te topas con él y es más fácil buscar con cosas como Intellisense. También es una buena práctica para UI-Controls, cuando lo más probable es que siempre sepas el tipo (por ejemplo, TextBox) pero no estés 100% seguro del nombre descriptivo que le diste.

El lado negativo es que se ve mal cuando el tipo en sí comienza con T. Por lo tanto, creo que sería bueno sufijar el tipo genérico en casos especiales, como el siguiente.

class SomeAlgorithm<TypeT> where TypeT : Type

Tenga en cuenta que esta es solo mi opinión y altamente subjetiva. Pero creo que tengo un punto menor al preferir el prefijo al sufijo.

Halcón
fuente
El uso del Tprefijo para los parámetros de tipo y Ipara los nombres de interfaz se requiere explícitamente ( reglas " DO ...") en las Pautas de diseño del marco.
Richard
1
Es cuestionable lo que usar TFruitaquí trae a la mesa T. Usar nombres como TTypeo TypeTes ciertamente una tontería. No agrega información alguna sobre solo T. Se transmite exactamente la misma información.
Konrad Rudolph
@Konrad Rudolph: Mira de cerca mi ejemplo de TypeT, cubre un caso especial cuando se trata de System.Type. Creo que mis nombres tienen una entropía más alta que simplemente usar T para el tipo, especialmente si el genérico también está restringido.
Falcon
7

Microsoft tiene una directriz oficial con respecto a los genéricos: nombres de clases, estructuras e interfaces (citado aquí y en forma de libro: Pautas de diseño de marcos ).

En cuanto a su pregunta específica, dice:

Nombre los parámetros de tipo genérico con nombres descriptivos, a menos que un nombre de una sola letra se explique por sí solo y un nombre descriptivo no agregue valor.

IDictionary<TKey, TValue> 

es un ejemplo de una interfaz que sigue esta directriz.

Considere usar la letra T como el nombre del parámetro de tipo para los tipos con un parámetro de tipo de letra única.

Haga prefijos de nombres de parámetros de tipo descriptivo con la letra T.

Considere indicar restricciones colocadas en un parámetro de tipo en el nombre del parámetro. Por ejemplo, un parámetro restringido a ISession puede llamarse TSession.

Matthieu
fuente
Una mejor referencia sería el libro de Pautas de diseño del marco o el (resumen) en MSDN, en particular los Nombres de clases, estructuras e interfaces .
Richard
@ Richard: ajustó mi respuesta teniendo en cuenta tu comentario, ¡Gracias!
Matthieu
2

El objetivo de los genéricos es delegar la funcionalidad: la clase genérica hace una cosa, su argumento hace otra. El ejemplo del libro de texto es una colección genérica: la colección almacena 'cosas', pero no le importa cuáles son estas cosas. Un nombre genérico (sic!), Por lo tanto, tiene una cierta lógica: no queremos que sea descriptivo, porque no hay nada que describir más que "es el argumento de tipo genérico", que el nombre Tabarca exhaustivamente (considerando la Convención). Ser descriptivo es bueno, pero ser demasiado descriptivo sugiere restricciones que no existen.

A veces, sin embargo, una clase o método genérico tiene más de un parámetro de tipo, y en este punto, tiene sentido darles nombres más descriptivos, de modo que su rol se vuelva obvio. Un buen ejemplo sería para un tipo de colección de clave-valor, donde clave y valor son genéricos; llamarlos Ty S(o Qlo que sea) sería menos útil que llamarlos, digamos, KeyTypey ValueType, o TKeyy TVal.

tdammers
fuente
1

La respuesta es de hecho subjetiva. Sin embargo, tiene mérito como pregunta, ya que el código debe autodocumentarse, y posiblemente todos podamos aprender algunas formas mejores de hacerlo.

Las siguientes son las convenciones que aprendí y sigo:

  • Los parámetros de tipo genérico nunca deberían confundirse con clases concretas. Esto generalmente fomenta un prefacio Tindependientemente de lo que sigue, al igual que las interfaces generalmente están precedidas I.

  • Un único parámetro de tipo genérico en una clase o método generalmente debe etiquetarse T. Esta es una convención casi universalmente entendida que se remonta a las plantillas de C ++.

  • Múltiples parámetros de tipo genérico en la misma declaración de clase o método deben comenzar con T, pero deben diferenciarse por algún medio conciso pero comprensible. TIny TOut, por ejemplo, son GTP comunes y bien entendidos para un método que acepta una entrada genérica fuertemente tipada y produce una salida genérica fuertemente tipada.

  • Múltiples tipos diferenciados pero no notables, como para una clase que contiene como .Net's Tuple o tipos de delegado como Func, Predicate y Action, pueden etiquetarse como T1, T2, T3, etc. Sin embargo, las declaraciones GTP "notables" (que tienen un propósito definido y / o restricciones de tipo muy específicas) debería tener algo más descriptivo.

  • Un único tipo genérico en un método, que difiere del tipo genérico de una clase que lo contiene, puede seguir la regla anterior con respecto a varios tipos en una clase o método, O si el tipo no es notable, aparte de ser diferente, se le puede dar una diferente sola letra, a menudo Uo V. Esto es nuevamente una convención que se remonta a las plantillas de C ++.

  • Lo que elija hacer, manténgalo constante; no etiquete un GTP para una clase T, y la siguiente TParam, a menos que la segunda clase esté anidada en la primera y Tno esté disponible para su uso en la segunda.

KeithS
fuente