A veces me encuentro en una situación en la que quiero expresar un tipo, que es un subtipo de una clase incorporada (por ejemplo, un control de Wiforms) y también implementa una interfaz personalizada. Tengo varias clases de este tipo que, de lo contrario, no tienen relación entre sí. Utilizo genéricos en estos casos. A continuación, se muestra un ejemplo simplificado:

interface IDescription
{
  string GetDescription();
}

...

private string getDescription<T>(T control) where T : System.Windows.Forms.Control, IDescription
{
  return control.Name + control.GetDescription();
}

Sin embargo, esto parece un uso poco convencional de genéricos, porque los genéricos generalmente se usan para escribir código de tipo agnóstico (como contenedores genéricos). En este código, por otro lado, los genéricos se utilizan únicamente debido a la falta de suficiente expresión de tipos.

Mi pregunta es: ¿Es esto un abuso de genéricos? ¿Existe alguna forma mejor de escribir dicho código?

ACTUALIZACIÓN 1

Como señaló Frank Hileman en este ejemplo, agregar la propiedad Name a la interfaz haría que esto no fuera un problema. Permítanme agregar otro ejemplo:

private string getDescription<T>(T control) where T : System.Windows.Forms.Control, IDescription
{
  return getData(control) + control.GetDescription();
}

private string getData(System.Windows.Forms.Control control)
{
  ...
}

ACTUALIZACIÓN 2

Tenga en cuenta que a veces no es posible agregar una clase base. Por ejemplo:

Tal vez haya una subclase de clase personalizada TreeNode y otra subclase DataGridView.

4
Gábor Angyal 29 ene. 2015 a las 00:58

2 respuestas

La mejor respuesta

No, no es. El hecho de que los genéricos se utilicen para crear contenedores genéricos, etc., no significa que sea el único caso de uso de genéricos.

En este caso, dado que su método hace lo mismo para diferentes tipos que implementan una interfaz común, está completamente bien y no es un abuso.

4
Peter Mortensen 8 feb. 2018 a las 18:44

Si bien no es una forma mejor, otra forma de escribir el método getDescription es escribir un método no genérico tomando un Control o IDescription como entrada y realizando una conversión dinámica para obtener una vista de la instancia como un tipo de datos diferente. Sin embargo, ahora cualquier tipo de error se producirá en tiempo de ejecución en lugar de en tiempo de compilación. Si está seguro de que todas las IDescription también son controles, funcionaría.

Otra opción es poner una propiedad Name en IDescription y usar solo IDescription.

1
Frank Hileman 28 ene. 2015 a las 22:17