.NET - Apresentando e usando Métodos Genéricos (VB .NET) - II
Neste artigo vou apresentar os conceitos e mostrar como podemos usar métodos genéricos na linguagem VB .NET. |
Eu vou repetir aqui os conceitos já descritos na
primeira parte deste artigo visto que eles são os
mesmos para a linguagem VB .NET.
Assim se você chegou diretamente neste artigo veja na primeira parte os conceitos usando a linguagem C#.
O que são métodos genéricos ?
Um método genérico é um método que é declarado com parâmetros de tipo.
Os métodos tradicionais trabalham com parâmetros e retornos fortemente tipados, ou seja, a todo momento conhecemos os tipos concretos dos argumentos que recebemos e dos valores que retornamos. |
Assim, métodos genéricos têm parâmetros de tipo e proporcionam uma maneira de
parametrizar os tipos utilizados em um método.
Isto significa que você pode fornecer uma implementação e pode chamar o método
com tipos diferentes.
Métodos genéricos são uma forma poderosa de fornecer segurança de tipo e ainda
criar métodos flexíveis que suportam vários tipos.
A ideia por trás de um método genérico é simples:
um método genérico aceita parâmetros e
retorna valores de uma gama de diferentes tipos.
Por isso, ele é chamado genérico.
A sintaxe usada para criar métodos genéricos pode parecer a primeira vista um
tanto incomum. A forma de sintaxe para a declaração usa os caracteres <T>
após o nome do método, mas antes da lista de parâmetro formal.
Nota: Todos os exemplos foram feitos no Visual Studio Express 2013 for Windows desktop.
Vejamos um exemplo:
Private Shared Sub Trocar(Of T)(ByRef lhs As T, ByRef rhs As T)
Dim temp As T
temp = lhs
lhs = rhs
rhs = temp
End Sub
|
Neste código temos a declaração do método genérico Trocar(Of T) que vai receber dois argumentos de quaisquer tipo e realizar a troca de valores entre os argumentos recebidos.
Podemos usar este método da seguinte forma:
Module Module1
Sub Main()
Dim a As Integer = 10
Dim b As Integer = 20
Trocar(Of Integer)(a, b)
Console.WriteLine(a.ToString() + " " + b.ToString())
Console.ReadKey()
Dim x As String = "primeiro"
Dim y As String = "segundo"
Trocar(Of String)(x, y)
Console.WriteLine(x.ToString() & " " & y.ToString())
Console.ReadKey()
End Sub
Private Sub Trocar(Of T)(ByRef lhs As T, ByRef rhs As T)
Dim temp As T
temp = lhs
lhs = rhs
rhs = temp
End Sub
End Module
|
Note que procuramos representar no código uma ideia conceitual do tipo : "Meu método vai receber dois objetos de um tipo T qualquer e vai trocar os valores dos objetos"
Antes de mostrar outro exemplo de método genérico vamos definir um método tradicional que se propõe a fazer a mesma tarefa: Obter o valor máximo entre dois objetos.
Um código possível para realizar tal tarefa seria:
Public Function Max(ByVal val1 As Double, ByVal val2 As Double) As Double
Return IIf(val2 < val1, val1, val2)
End Function
|
Qual o problema com o código acima ?
Nenhum, mas o método somente pode ser aplicado a tipos de dados Double.
Suponha que agora eu quero representar via código a seguinte ideia conceitual : "Meu método vai receber dois objetos de um tipo T que implemente a interface IComparable e vai retornar o maior deles"
Public Function Maximo(Of T As IComparable)(valor1 As T, valor2 As T) As T
If valor1.CompareTo(valor2) > 0 Then
Return valor1
End If
Return valor2
End Function
|
O método genérico Maximo<Of T> vai processar qualquer tipo T. Os parâmetros de entrada também são do tipo T e o retorno também e do tipo T.
A seguir temos um exemplo de como usar o método genérico criado acima:
Module Module1
Sub Main()
Dim maiorString As String = Maximo("Macoratti", "Jefferson")
Dim maiorInteiro As Integer = Maximo(2, 99)
Dim maiorDouble As Double = Maximo(445.98, 98.65)
Console.WriteLine("Maior String = {0} ", maiorString)
Console.WriteLine("Maior Inteiro = {0} ", maiorInteiro.ToString())
Console.WriteLine("Maior Double = {0} ", maiorDouble.ToString())
Console.ReadKey()
End Sub
Public Function Maximo(Of T As IComparable)(valor1 As T, valor2 As T) As T
If valor1.CompareTo(valor2) > 0 Then
Return valor1
End If
Return valor2
End Function
End Module
|
Neste exemplo observe que temos uma restrição no método que diz que o tipo T deve implementar a interface IComparable().
Usando essa linha de raciocínio existem vários tipos de restrições que podem ser utilizadas para limitar os tipos permitidos para os nossos métodos parametrizados. Abaixo temos algumas delas:
As Structure, indica que o argumento deve ser um tipo de valor.
As Class, indica que T deve ser um tipo de referência.
As New(), obriga que o tipo T tenha um construtor público sem parâmetros;
AS nomeClasse, indica que o argumento deve herdar ou ser desse tipo.
As nomeInterface, o argumento deve implementar a interface indicada.
As nomeTipoGenerico indica que o argumento a que se aplica deve ser igual ou herdar do tipo, também argumento do método, indicado por nomeTipoGenerico.
Suponha que você queira restringir os tipos do método Trocar (que vimos no
início do artigo) para tipos de estrutura não anuláveis. Você pode
adicionar uma restrição no Trocar para indicar que ele é aplicável somente aos
tipos de valores (estruturas).
No código abaixo temos que o método Trocar agora é definido como sendo
restrito a estruturas (ou tipos de valor).
Public Sub Trocar(Of T As Structure)(ByRef a As T, ByRef b As T)
Dim temp As T
temp = a
a = b
b = temp
End Sub
|
Para concluir vejamos agora um exemplo um pouco mais complexo. O método genérico CriaLista, aplicável a qualquer classe, retorna uma lista genérica (List(Of T)) do tipo parametrizado do método, inicialmente preenchida com os argumentos (variáveis) que são fornecidos:
Public Function CriaLista(Of T)(ParamArray pars As T()) As List(Of T)
Dim lista As New List(Of T)()
For Each elem As T In pars
lista.Add(elem)
Next
Return lista
End Function
|
A seguir vamos usar este método:
Module Module1
Sub Main()
Dim numeros As List(Of Integer) = CriaLista(Of Integer)(1, 2, 3, 4, 6, 7)
Dim nomes As List(Of String) = CriaLista(Of String)("Macoratti", "Jefferson", "Miriam", "Janice")
For Each numero As Integer In numeros
Console.WriteLine(numero.ToString() + " ")
Next
Console.ReadKey()
For Each nome As String In nomes
Console.WriteLine(nome & " ")
Next
Console.ReadKey()
End Sub
Public Function CriaLista(Of T)(ParamArray pars As T()) As List(Of T)
Dim lista As New List(Of T)()
For Each elem As T In pars
lista.Add(elem)
Next
Return lista
End Function
End Module
|
Sobrecarga de Métodos genéricos
Os métodos podem ser sobrecarregados com base em argumentos, mas não em tipos de
retorno e métodos também podem ser sobrecarregados por tipos parametrizados.
Por exemplo, todos os seguintes métodos podem existir no mesmo escopo:
Sub Teste() End Sub Sub Teste(ByVal s As String) End Sub Sub Teste(Of T)(ByVal arg As T) End Sub Sub Teste(Of T, U)(ByVal arg1 As T, ByVal arg2 As U) End Sub |
Pegue o projeto completo aqui: Metodos_Genericos_VBNET.zip
Quem
ama a sua vida perdê-la-á, e quem neste mundo odeia a sua vida, guardá-la-á para
a vida eterna.
Se alguém me serve, siga-me, e onde eu estiver, ali estará também o meu servo.
E, se alguém me servir, meu Pai o honrará.
João 12:25,26
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Gostou ? Compartilhe no Facebook Compartilhe no Twitter
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
C# - Classes Abstratas, Interface e Polimorfismo - Macoratti ...