martes, 26 de julio de 2011

Genéricos en VB.NET

Hace poco escribí un post sobre colecciones genéricas, por ejemplo Dictionary(Of TKey, TValue), también utilizo asiduamente tipos anulables con el formato Nullable (Of T)… y sin embargo, tengo la sensación de que no tengo excesivamente claro que son los genéricos en .NET. Es decir, utilizo intuitivamente las colecciones genéricas (es algo que una vez lo descubres ya no puedes volver a las no genéricas), los tipos anulables, pero el mundo “genérico” de .NET es mucho más que sólo colecciones y tipos anulables.

Los genéricos (Generics en inglés) permiten declarar clases, interfaces y métodos cuyo tipo de dato es genérico (el famoso Of T o <T>, dependiendo de VB.NET o C#).

De este modo, será el programador cuando utilice la clase quien especifique que tipo de dato en concreto va a utilizar para la clase, interface o método.  Siendo así, tenemos un único código que puede ser utilizado por distintas tipos de clases según decida el programador cuando haga uso del mismo.

Algunas de las ventajas de usar genéricos es que en tiempo de compilación se validan los tipos, es decir, si declaro un Nullable (Of Int32) sólo podré almacenar enteros y además evitaremos castings innecesarios (porque conocemos el tipo y sólo pudimos guardar instancias de ese tipo). Por otro lado, las instancias se guardan en su tipo original, no hay boxing y unboxing porque no se utiliza el tipo Object sino el tipo concreto que hemos especificado.

Por ejemplo, podemos definir nuestra propia clase genérica

Public Class Saludador(Of T)


En esta clase podemos definir métodos que reciben parámetros del tipo genérico

Public Sub Saludar(ByVal saludo As T)


Después, y cuando ya estemos usando la clase, crearemos una instancia con un tipo concreto.

Dim s As New Saludador(Of Integer)

s.Saludar(5)

 

clip_image002

clip_image004

clip_image005

También tenemos métodos genéricos. En estos métodos no sólo se puede recibir un parámetro del tipo de la clase genérica (T), sino otros muchos parámetros genéricos (T1, T2, etc.). El método de declararlos es el siguiente:

Sub|Funcion <Nombre>(Of T, T1, T2, etc.) (ByVal <Nombre> AS T, ByVal <Nombre> AS T1, ByVal <Nombre> AS T2, etc.)

Public Class Saludador(Of T)

 

    ' Propiedad genérica que será tipada al tipo de datos de la clase durante su instanciación

    Property Propiedad1 As T

 

    ' Método genérico que recibe 3 parámetros de tipo genérico y un tipo no genérico (Boolean)

    Public Sub Saludar(Of T1, T2, T3)(ByVal a As T1, ByVal b As T2, ByVal c As T3, ByVal d As Boolean)

 

    End Sub

End Class

 

clip_image006

clip_image007

Las ventajas de los genéricos ya las hemos comentado antes pero, en mi opinión, creo que lo más reseñable es que permiten crear código reutilizable fuertemente tipado, y es justamente este “fuertemente tipado” quien nos da la seguridad de no estar guardando tipos no admitidos, nos da intellisense, nos evita el boxing y unboxing, etc.

Cabe mencionar que a nivel personal sólo he utilizado los genéricos como parte de las colecciones genéricas, pero odio encontrar código de terceros que no puedo leer, así que este post lo que pretendía era arrojar un poco de luz sobre los genéricos y por supuesto no sentar cátedra ;-)

Un ejemplo muy clarificador de cómo utilizar genéricos en el mundo real se puede encontrar en http://geeks.ms/blogs/jmaguilar/archive/2008/12/08/m-233-todos-gen-233-ricos-en-vb-net.aspx

Un saludo!

No hay comentarios:

Publicar un comentario