¿Cómo funciona T en C? Cómo usar parámetros de tipo genérico

Tabla de contenido:

¿Cómo funciona T en C? Cómo usar parámetros de tipo genérico
¿Cómo funciona T en C? Cómo usar parámetros de tipo genérico
Anonim

En C, el parámetro "T" se usa a menudo para definir funciones que toman cualquier tipo. Se utilizan para escribir clases y métodos genéricos que pueden funcionar con cualquier tipo de datos, al mismo tiempo que mantienen una estricta seguridad de tipos. Discutiremos cómo funcionan y cómo usarlos.

¿Cómo funciona?

La variable "T" que probablemente haya visto en algunas definiciones de métodos se denomina parámetro de tipo genérico, o simplemente "genérico". Los métodos genéricos que usan T se pueden usar con cualquier tipo, lo que facilita la definición de clases y métodos que no se preocupan por los datos que manejan pero que desean preservarlos.

Por ejemplo, las colecciones hacen uso de genéricos, para que puedan manejar cualquier cosa que el usuario les arroje. No hay una definición diferente para

List

y

List

; en cambio, hay una definición para

List.

En la práctica, se parece a lo siguiente. Aunque esta es una clase y no un método, aún puede pasarle parámetros de tipo usando la sintaxis de paréntesis. Luego, en cualquier lugar donde necesite hacer referencia a algo de este tipo, simplemente sustituya el parámetro en su lugar.

Pase los parámetros de tipo utilizando la sintaxis de paréntesis. class=imgchk9 alignnone wp-image-6502 tamaño completo
Pase los parámetros de tipo utilizando la sintaxis de paréntesis. class=imgchk9 alignnone wp-image-6502 tamaño completo

Poner cualquier cosa entre paréntesis le permite usar ese nombre en lugar de un tipo válido, en cualquier parte de la definición de la clase o método que está usando ese parámetro. Si imagina una

GenericList

, en cualquier lugar que escriba

int

como un tipo, en su lugar escribiría

T, y deje que el usuario le diga a esta clase qué tipo usar.

Es realmente así de simple. Para una

GenericList

, el código anterior es funcionalmente equivalente a escribir lo siguiente, aunque debe tenerse en cuenta que esta definición no incluye

GenericList, porque todo lo que está entre paréntesis son parámetros de tipo y las primitivas no se pueden usar como nombres de tipo. Para una clase que no usa ningún parámetro, como esta, se define como siempre sin corchetes.

Una clase que no utiliza ningún parámetro se define sin corchetes
Una clase que no utiliza ningún parámetro se define sin corchetes

En realidad, puedes nombrar esta variable T como quieras, aunque es una práctica común comenzar al menos con "T". Si tiene una función que necesita argumentos de varios tipos, puede nombrarlos de manera diferente, como "TOutput" o "TInput". Esto se usa mucho en definiciones de delegados y en diccionarios donde tiene TKey y TValue.

Mala práctica de nombres
Mala práctica de nombres

Por supuesto, también puede usar genéricos en métodos, así como interfaces y delegados. Funcionan de la misma manera, e incluso puede pasar el parámetro de tipo como parámetro de tipo a otra función.

Usar genéricos en los métodos
Usar genéricos en los métodos

Sin embargo, cabe destacar que puede utilizar el parámetro de tipo en los parámetros reales de la función. Aún deberá ponerlo entre paréntesis; de lo contrario, será un tipo no válido, pero puede usar el parámetro en cualquier lugar de la definición de este método.

Utilice el parámetro de tipo en los parámetros reales de la función
Utilice el parámetro de tipo en los parámetros reales de la función

Son particularmente útiles en delegados, porque puedes usarlos para aceptar funciones con parámetros variables.

Restricciones de tipo

Los genéricos son geniales, pero pueden causar algunos problemas cuando se permite que la función tome cualquier tipo posible que le arrojes. A veces, es mejor poner algunas restricciones de uso.

Esto se hace con la sintaxis

where T:

. La forma más simple de esto es

donde T: ClassName

, lo que asegura que el parámetro T debe ser o derivar del tipo dado

ClassName

Esto permite escribir- polimorfismo seguro, como esta función que toma cualquier tipo de Fruta, y devuelve una

Lista

, en lugar de una

Lista, que sería técnicamente correcto pero pierde valiosa información de tipo.

Polimorfismo con seguridad de tipos
Polimorfismo con seguridad de tipos

Puedes ver que si tratamos de usar esta función con cualquier cosa que no sea una fruta, el compilador te gritará.

Si usa esta función con cualquier cosa que no sea una fruta, el compilador comentará
Si usa esta función con cualquier cosa que no sea una fruta, el compilador comentará

Más allá de la herencia simple, hay algunas restricciones más útiles:

  • donde T: InterfaceName

    – como

    T: ClassName pero se asegura de que el argumento tipo implemente la interfaz dada.

  • donde T: class – asegura que el argumento de tipo es un tipo de referencia.

  • donde T: struct – asegura que el argumento de tipo es un tipo de valor no anulable.

  • donde T: notnull – el argumento de tipo debe ser un tipo no anulable.

  • donde T: new() – el argumento de tipo debe poder construirse sin parámetros.

  • donde T: TOther

    – el argumento de tipo

    T

    debe ser, o derivar de, el argumento de tipo

    TOther.

Puede especificar varias restricciones en una lista separada por comas.

Tema popular