Desenvolvimento - Visual Basic .NET

Structures - Muito mais que uma mudança de Sintaxe do Type do VB

O equivalente em .NET é o Structure / End Structure, mas não é apenas uma mudança de sintaxe, tem muito mais coisa que as Structures podem fazer...

por Fernando Cerqueira



Quando precisávamos implementar uma estrutura de dados mais complexa em VB 6 usávamos Type / End Type. O equivalente em .NET é o Structure / End Structure, mas não é apenas uma mudança de sintaxe, tem muito mais coisa que as Structures podem fazer tendo várias semelhanças a uma classe, como por exemplo, propriedades e métodos.

Estrutura de dados é a base, o fundamento para a boa organização das informações, e conseqüentemente sua recuperação e fácil legibilidade. Vamos a um exemplo simples :

Structure  Stru_Usu 	
	Dim Nome as string	
	Dim Cidade as string	
	Dim Uf as string	
	Dim Idade as integer
End Structure

No exemplo acima criamos uma estrutura complexa e atribuímos esta organização ao um tipo de nome Stru_Usu. Em nosso código para referenciarmos e consumirmos esta estrutura basta declarar uma variável com este tipo e utilizá-la na forma de Tipo.propriedade desta forma :

Dim MyUsu as new Stru_Usu
MyUsu.Nome = "Fernando"
MyUsu.Cidade = "Rio de Janeiro"
MyUsu.Uf = "rj"
MyUsu.Idade =  39

Bem até aqui não existe nada de novo em relação ao que conhecíamos.... Porém na forma apresentada traz algumas desvantagens :

  • Não é possível encapsular os dados dentro da estrutura restringindo sua visibilidade
  • Não é possível executar tratamento dos dados quando recebidos e ou devolvidos
  • Não é possível restringir um dos dados a apenas leitura ou a apenas gravação
  • Não é possível criar regras de funcionalidades para esta estrutura.
Vamos ver como isso agora é possível em .NET, criando novas necessidades na estrutura acima para podermos demonstrar as novas funcionalidades :
  1. A idade na estrutura devera ser trocada por um campo DataNascimento , desta forma teremos sempre como saber a real idade do usuário.
  2. Deverá ter uma forma de apresentar a idade do usuário da mesma forma que a estrutura anterior.
  3. O campo UF, deverá apresentar sempre o estado em letras Maiúsculas, podem e deve ser permitido o input em qualquer formato. Além disso deve ser criado um mecanismo de validar o conteúdo e poder gerenciar quando ocorrer um dado inválido.

Olhando as novas necessidades, na forma que conhecíamos de Type / End Type não seria possível, sem ter que criar uma classe para isso, porém todas podem agora ser implementadas dentro de uma Structure.

Como já foi dito é possível agora criar propriedades e métodos para uma Structure , funcionando da mesma forma que uma classe, com isso poderemos resolver os itens A, B e parcialmente o "C".

Para resolver o item "C" em sua totalidade nossa Structure também deverá ser capaz de dispor de uma forma de poder gerenciar um input de UF não válido, que poderemos resolver utilizando um evento, sim Structure também aceitas Eventos!

Falar apenas não basta....Qual desenvolverdor que se contenta com isso...rs.rs.rs, então vamos ao código da definição da estrutura :

Definindo Structure

	Structure Stru_Usu
Criando as Variáveis púbicas e privadas
  Dim Nome As String
  Dim Cidade As String
  Private LCDataNacimento As Date
  Private LcIdade As Integer
  Private LcUf As String

No código acima restringimos 3 variáveis (LCDataNacimento ,LcIdade, LcUf) como privates, desta forma serão apenas visíveis dentro da própria estrutura, onde faremos algum tratamento para poder atender as novas necessidades , então vamos as elas :

- Tratando a DatadeNascimento para alimentar a variável Idade

    Public Property DataNacimento() As Date
        Get
            Return LCDataNacimento
        End Get
        Set(ByVal Value As Date)
            LCDataNacimento = Value
            LcIdade = System.DateTime.Now.Year - LCDataNacimento.Year
        End Set
    End Property
Observe que durante a entrada do valor da Data fazemos o cálculo da Idade baseada na data atual e guardamos o resultado em nossa variável local LcIdade e abaixo dados o tratamento de saída para ela que é somente de leitura, pois ela passou a ser função da data de Nascimento.

- Tratando o retorno da Idade

    Public ReadOnly Property Idade() As Integer
        Get
            Return LcIdade
        End Get
    End Property
Vamos tratar agora a UF no código abaixo. Neste exemplo apenas usamos 2 estados (por favor sem "bairrismo"..rs.rs). Iniciamos convertendo o parâmetro em maiúscula e logo após executando uma busca por uma igualdade dentro de um array de UF. Caso não seja encontrado disparamos o evento InvalidUF e repassamos o parâmetro. Com isso deixamos a cargo da implementação a melhor forma de tratar esta exceção.

Finalmente definimos para nossa Structure o evento para ser usado dentro de nosso código. Obs : Foi deixado a opção de aceitar uma uf vazia, para efeito do tratamento de exceção poder limpar o conteúdo da variável.

- Tratando a entrada / saída da UF e disparando um evento

    Public Property UF() As String
        Get
            Return LcUf
        End Get

        Set(ByVal Value As String)
            If Value = "" Then
                LcUf = Value
            Else
                Dim listaUF() As String = {"RJ", "SP"}
                Value = Value.ToUpper
                If Array.BinarySearch(listaUF, Value) < 0 Then
                    RaiseEvent InvalidUF(Value)
                Else
                    LcUf = Value
                End If
            End If
        End Set
    End Property

    Public Event InvalidUF(ByVal UF As String)

Concluindo a Structure

    End Structure
Abaixo o código completo da estrutura e um exemplo de sua utilização dentro do código :
    
Structure Stru_Usu         
	Dim Nome As String        
	Dim Cidade As String        
	Private LCDataNacimento As Date        
	Private LcIdade As Integer        
	Private LcUf As String        
	Public Property DataNacimento() As Date            
		Get                
			Return LCDataNacimento            
		End Get            
		Set(ByVal Value As Date)                
			LCDataNacimento = Value                
			LcIdade = System.DateTime.Now.Year - LCDataNacimento.Year            
		End Set        
	End Property        
	Public ReadOnly Property Idade() As Integer            
		Get                
			Return LcIdade            
		End Get        
	End Property        
	Public Property UF() As String            
		Get                
			Return LcUf            
		End Get            
		Set(ByVal Value As String)                
			If Value = "" Then                    
				LcUf = Value                
			Else                    
				Dim listaUF() As String = {"RJ", "SP"}                    
				Value = Value.ToUpper                    
				If Array.BinarySearch(listaUF, Value) < 0 Then  
					RaiseEvent InvalidUF(Value)                    
				Else                        
					LcUf = Value                    
				End If                
			End If            
		End Set        
	End Property        
	Public Event InvalidUF(ByVal UF As String)    
End Structure
Usando a Estrutura criada :
	Sub TratamentodeUFInvalida(ByVal Uf As String)         
		"implemtente aqui seu tramento personalizado    
	End Sub    
	Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) 
Handles MyBase.Load        
		Dim MyStru As New Stru_Usu        
		AddHandler MyStru.InvalidUF, AddressOf TratamentodeUFInvalida        
		MyStru.UF = "AM"    
End Sub

No exemplo acima adicionamos um Handler usando AddHandler à nossa Structure para efetuar um tratamento de exceção pela procedure TratamentodeUFInvalida. A intenção tanto do código como do exemplo de uso é apenas demonstrar que uma Structure é muito mais que uma simples definição como muitas vezes se pensa. Passamos a ter agora muito mais flexibilidade e poder de implementação.

Acredito que neste momento você esteja se perguntando então :

Hummm, se ela pode fazer isso tudo então para quer criar Classes, ou melhor o que uma Structure é diferente de uma Classe?

Faz muito sentido esta pergunta, e realmente muitas coisa ambas podem fazer, mas existem muitas diferenças entre elas, então para finalizarmos vamos ver apenas algumas delas:

Estas são apenas algumas, existem bem mais restrições e diferenças.

Uma relação mais completa pode ser encontrada no Help do VS procurando por Structures and Classes ou on line no MSDN no link abaixo :
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcn7/html/vaconstructuresandclasses.asp

Espero que com este breve artigo o leitor possa vislumbrar melhor as implementações que foram realizadas no VB.NET, não sendo um upgrade de versão, mas sim uma nova concepção da linguagem, que embora tenha seu legado anterior foi totalmente reescrita.

Sobre o Autor: Fernando Cerqueira - Analista de Sistemas, tendo trabalhado em empresas de todos portes. Atualmente é Consultor e diretor da FCI (www.fci.com.br) , DEVELOPER por vocação, ministrando palestras e atuando em soluções personalizadas na plataforma .NET para diversas empresas.E-mail de Contato : fernandocerqueira@msn.com

Fernando Cerqueira

Fernando Cerqueira - Microsoft Most Valuable Professional em ASP.NET 2004 – 2005 – 2006 . Possui formação Acadêmica em Administração de empresas, especialista em Call Center , BI e CRM. Atuou em diversas empresas de grande porte, sempre utilizando a plataforma Microsoft. Desde 2002 vem trabalhando com o Visual Studio .NET prestando consultoria e treinamento focando os resultados em ASP.NET. Em 2003, criou o GURJ.NET - Grupo de usuários .NET do Rio de Janeiro sendo reconhecido pelo INETA. Hoje voluntariamente dedica parte de seu tempo no comitê de Web e Infra da INETA Brasil. Atualmente, como profissional, presta serviços exclusivamente na plataforma Microsoft.NET atuando como arquiteto de sistemas em diversos projetos de porte nos estados do RJ, SP e MG.