Escolar Documentos
Profissional Documentos
Cultura Documentos
39 Visual Basic Net
39 Visual Basic Net
Net
Autor:
Paulo Cesar Macedo
Apostila de VISUAL STUDIO .NET
1 - Introdução ao Visual Basic .NET .....................................................................................................3
1.1 – Hardware necessário para instalação ........................................................................................3
1.2 – Conceitos para o desenvolvimento de aplicativos Microsoft ...................................................4
2 - Estudo da Linguagem Visual Basic .NET ........................................................................................8
2.0 – Arquivos gerados pelo Visual Basic .NET ...............................................................................8
2.1 - Nova Estrutura do programa escrito em VB .Net....................................................................10
2.2 – Atribuir nomes aos elementos do seu programa .....................................................................11
2.3 – Utilizando quebra de linha e combinação de código ..............................................................11
2.4 – Caracteres especiais no VB .Net .............................................................................................12
2.5 – Criar comentários no Código ..................................................................................................12
2.6 – Limitações do Visual Basic .NET...........................................................................................13
2.7 - Compilação Condicional .........................................................................................................13
2.7.1 – Criando Constantes de declaração Condicional...............................................................14
2.7.2 – Ocultando ou expandindo o código .................................................................................14
2.8 – Técnicas de codificação e programação .................................................................................14
2.9 – Declarando Elementos ............................................................................................................20
2.10 – Tipos de Dados .....................................................................................................................27
2.10.1 – Estruturas de dados ........................................................................................................37
2.10.2 – Matrizes (Arrays) ...........................................................................................................38
2.11 – Objetos ..................................................................................................................................44
2.12 – Strings ...................................................................................................................................46
2.13 - Constantes e Enumerações ....................................................................................................49
2.14 – Operadores ............................................................................................................................52
2.15 – Procedures (Procedimentos) .................................................................................................62
2.16 - Collection (Coleções) ............................................................................................................73
2.17 - Estruturas de Controle de Fluxo ............................................................................................76
2.18 - Visual Basic .NET e a programação orientada a objeto ........................................................84
2.18.1 – Early bound e Late bound ..............................................................................................85
2.18.2 – Palavra chave New e liberando recursos do Sistema.....................................................86
2.18.3 – Trabalhando com Grupos de Objetos ............................................................................87
2.18.4 - Obtendo informações de uma classe ..............................................................................88
2.18.5 - Classes ............................................................................................................................89
2.18.6 – Propriedades, Campos e Métodos de uma Classe..........................................................98
2.18.7 – Eventos e Delegar ........................................................................................................103
2.18.8 – Interfaces no VB .NET ................................................................................................110
2.18.9 – Herança (Inherits) ........................................................................................................112
2.18.10 – Construtores e Destrutores na hierarquia de classes ..................................................118
2.18.11 – Polimorfismo..............................................................................................................120
2.18.12 – Criando um hierarquia de heranças............................................................................122
2.19 – Operações com Componentes COM...................................................................................123
2.20 – Multithreading.....................................................................................................................125
2.21 – Drivers, Pastas e Arquivos ..................................................................................................129
2.21.1 - A classe System.IO.......................................................................................................129
2.21.2 – Acessando arquivos com as funções internas do VB...................................................130
2.21.3 – Acessando arquivos com FileSystemObject................................................................138
2.22 – Manipulando exceções (Exception) ....................................................................................141
2.22.1 – Manipulador estruturado de exceções..........................................................................141
2.22.2 – Manipulador de exceções não estruturado ...................................................................143
3 – Visão Geral da Tecnologia .NET Framework .............................................................................146
3.1 – Infraestrutura NET ................................................................................................................146
2
1 - Introdução ao Visual Basic .NET
A Microsoft lançou as versões mais significativas do Visual Basic, conforme abaixo :
O pacote Visual Studio .NET substitui e aposenta o Visual Studio 6.0 e anteriores, assim como o
Visual Basic .NET substitui e aposenta o VB 6.0, 5.0 e 4.0. O VB .NET faz parte do pacote Visual
Studio .NET.
Agora, o Visual Basic 7.0 ou Visual Basic .NET (pronuncia-se DOT NET) pode ser usado para criar
qualquer aplicativo Windows Cliente, Servidor, Internet, não precisando usar nenhuma outra
ferramenta.
O Visual Basic só trabalha com a Tecnologia .NET e de agora em diante qualquer aplicativo criado
com o Visual Basic .NET é GERENCIADA e não mais interpretada ou nativa (VB 6.0), além disso,
utiliza novos recursos de desenvolvimento procedentes do C++.
O Visual Basic é uma ferramenta denominada pela Microsoft de RAD – Rapid Application
Development que possibilita a criação de aplicativos rapidamente sem preocupar-se com os detalhes
da programação Windows, é portanto uma ferramenta de alta produtividade.
Visual – É o componente que é usado para criar a Interface Gráfica de Usuário (GUI), assim você
usa os objetos pré-construídos para criar a sua tela. Se não fosse por intermédio desse componente,
você seria obrigado a digitar linhas e mais linhas de código para “desenhar” uma simples janela,
além de utilizar as centenas de funções API do Windows. O ambiente visual é conhecido como IDE
(integrated Development Enviroment) que possui um kit de ferramentas para o desenvolvimento.
Basic – É a linguagem Basic criada em 1964, adicionado de Métodos, Funções, Comandos,
Propriedades e Eventos. Tudo isso foi herdado do Ambiente gráfico do Windows.
Plataforma .NET – É um conjunto de centenas de classes e objetos pré-construídos pela Microsoft
para serem utilizados na codificação do aplicativo, além disso possui vários arquivos distribuídos a
serem compilados junto com o aplicativo.
O Visual Studio .Net não pode ser instalado em sistemas operacionais Windows 95, 98, Me. Além
disso para instalar as ferramentas de desenvolvimento Web é necessário o Windows 2000 Server ou
NT com o IIS (Internet Information Service) instalado na máquina.
Hardware necessário para cada versão do VS .NET :
3
Developer
Processador Pentium II-, 450 MHz Mesmo Mesmo Mesmo
Recomendado: Pentium III -
600MHz
RAM Windows 2000 Professional — Mesmo Mesmo mesmo
96 MB; Windows 2000 Server
— 192 MB; Windows NT4.0
Workstation — 64 MB;
Windows NT 4.0 Server — 160
MB; Windows XP Professional
— 160 MB
Recomendado: 128 MB - 2000
Professional, 256 MB - 2000
Server, 96 MB - Workstation,
and 192 MB - NT 4.0 Server,
192 MB - XP Professional
Espaço em Disco 500 MB no drive do sistema, 3 Mesmo Mesmo mesmo
GB drive de instalação
Sistema Windows® 2000, Windows Mesmo Mesmo mesmo
Operacional XP, ou Windows NT 4.0
CD-ROM ou Recomendado Recomendado Recomendado Recomendado
DVD-ROM
Video 800 x 600, 256 cores Mesmo Mesmo mesmo
Recomendado: High Color 16-
bit
Mouse Qualquer Mesmo Mesmo mesmo
Para melhorar a velocidade na inicialização do VS .Net feche a janela de propriedades da IDE; feche
a janela Start Up da IDE; feche a janela Dynamic Help. Observação desmarque a opção de abrir estas
janelas automaticamente.
Este capítulo foi incluído para explicar o significado de alguns termos que a Microsoft utiliza na
documentação oficial, e no treinamento para a certificação.
4
• O Modelo Físico – É o produto final que engloba os componentes, a distribuição e a
interconecção.
Para o programador VB a fase mais importante das descritas acima é o Modelo de Deesenvolvimento
(Model Development) que é o intermediário entre o Modelo de Negócios e os Modelos do Usuário,
Lógico e Tecnológico.
1 - O Modelo de desenvolvimento
O Desenho Conceitual irá considerar o perfil do usuário, isto é quem é o usuário e como ele irá
trabalhar com o sistema, além disso o perfil do usuário engloba sua função ou cargo.
O desenho conceitual também deve considerar o cenário atual em uso, isto é quantos usuários
utilizam o sistema atual e as situações de uso.
E finalmente o desenho conceitual deve considerar o cenário proposto para o uso, isto é quantos
usuários deverão utilizar o novo sistema e as situações de uso.
2 – O Desenho Lógico
Uma entidade que representa os modelos lógicos ou físicos é chamado de business object (Objeto
de Negócio, ou Objeto comercial), isto é representar as situações ou funções de uma empresa em
um objeto no sistema. Um business object pode retratar :
• Contas
• Clientes
• Vendas
• Faturas
O desenvolvimento do software irá implementar esses objetos para criar seus membros tais como
propriedades e métodos para interagirem com outros objetos. Para identificar um business object é
necessário determinar os nomes dos cenários em uso e os verbos dos cenários em uso.
Os nomes dos cenários podem ser determinados pelos diversos departamentos ou seções que irão
utilizar o aplicativo, e serve como base para identificar os verbos para compor o objeto.
Os verbos podem ser indicados pelos termos Possui ou Tem; Usa; Contém ou Guarda ou Consiste;
É um exemplo de ou É um.
5
3 – O Desenho Físico
Para criar o desenho Físico a partir do Desenho Lógico é preciso seguir estes passos :
• Definir o tipo de serviço aos componentes – Cria os componentes a partir dos objetos lógicos
já definidos e determina se cada objeto é um usuário, um negócio ou um objeto de serviços de
dados.
• Distribuir o componente na rede – Definir o local do componente na rede.
• Refinar a distribuição dos componentes – Agrupar os componentes de acordo com as
necessidades do sistema.
• Definir os membros do componente – Define o relacionamento entre os componentes.
• Validar o desenho físico – Certificar que cada componente corresponde ao serviço no objeto
lógico.
Um desenho lógico bem efetuado vai ter um impacto positivo na criação do desenho Físico. A forma
de medir o impacto do desenho lógico no desenho físico é observar se as considerações abaixo
podem ser alcançadas.
• Performance (Desempenho)
• Maintainability (Manutenciabilidade)
• Extensibility (Extensibilidade)
• Scalability (Escalabilidade)
• Availability (Disponibilidade)
• Security (Segurança)
Performance
Maintainability
O sistema que permite uma boa manutenção, isto é revisão do código fonte pelos programadores, é
aquele que evita um longo trabalho de revisão e a participação de usuários no processo.
Extensibility
6
Extensibilidade é a capacidade de integrar outros aplicativos ao sistema. Para alcançar a
extensibilidade pode-se utilizar as regras abaixo :
Scalability
Availability
Um sistema deve estar disponível na maior parte do tempo possível e na maioria dos lugares em que
for acessado. Para que um sistema esteja sempre disponível é necessário observar a natureza do
sistema e outros fatores tais como :
• Área local
• Rede
• Internet
• INtranet
Security
A segurança de um aplicativo está voltado a formas de evitar acessos externos e total controle da
administração do sistema. Para melhor segurança o sistema deve estar centralizado em um único
lugar para melhor administração e evitar acessos externos.
7
2 - Estudo da Linguagem Visual Basic .NET
Quando iniciado um projeto em VB, o sistema cria os arquivos com extensão .vb, além de outros que
podem ser incluídos no projeto tais como arquivos ASP que tem a extensão .aspx; arquivos XML
com extensão .xml; arquivos HTML com extensão .html e outros. Assim não há distinção de
arquivos de classes, janelas, controles e etc, pois todos terão a partir de agora a extensão .vb.
8
Arquivo JScript .js Arquivo contendo código JScript
Arquivo VBScript .vbs Arquivo contendo código VBScript
Windows Script Host .wsf Arquivo que contém Script que é executado como um
aplicativo Windows.
Ainda hoje, os arquivos do Vb podem ser abertos por qualquer programa de texto e podem ser
alterados diretamente sem usar o Ambiente de Desenvolvimento do Visual Studio.
A primeira linha funciona como comentário. O Comando Option obriga declarar todas as variáveis
antes de utilizá-las no programa.
No exemplo acima, no módulo “Olá” está o procedimento Sub Main ( ) que vai controlar a execução
do processo e exibir a mensagem “Olá Mundo” na tela do computador.
10
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
No exemplo acima, O VS .net criou o protótipo central para ser modificado, contendo uma janela
Form1 que possui o código inicial da janela Sub New que é o construtor da janela onde é colocado o
código de inicialização da janela que substitui o antigo evento Initialize do VB 6.0.
Resumindo, quando a janela é carregada na tela, o primeiro procedimento a ser executado será o
código dentro de Sub New, também conhecido como Construtor (proveniente da linguagem C++).
InitializeComponent( ) é criado automaticamente pelo VStudio e substitui o antigo arquivo .frm que
era criado pelo VB 6, onde continha todo as propriedades e códigos fonte da janela em formato de
Texto.
Resumindo, InitializeComponent( ) grava todas os controles, textos, figuras e outras coisas que
forem feitas na janela.
O comando inherits na primeira linha do exemplo acima herda todas as características de uma janela
normal. Assim pode-se alterar suas propriedades na janela de propriedades do VB.
Resumindo, para criar uma janela é preciso acionar a classe Windows Form da tecnologia .NET
Framework.
Quando for nomear (dar nome as variáveis, objetos ou classes) os elementos do seu programa a
Microsoft recomenda usar as seguintes técnicas.
• Começar cada Nome com letra maiúscula , Exemplo : ConvertaPrimeiraLetra.
• Quando nomear uma função ou método inicie com a ação que ela executa. Exemplo :
CarregarFiltro; IniciarProcura; FecharJanela.
• Quando nomear uma Classe ou uma propriedade da classe inicie com o nome a que se refere
a classe . Exemplo : CarroAcessórios; EmpregadosSalário; ArquivosNome.
• Quando nomear uma Interface (Interface) no seu programa, inicie com a letra I maiúscula
seguida da ação ou comportamento dessa interface. Exemplo : IPersistente; IAleatório.
• Quando nomear eventos para sua classe, inicie com a palavra “Event” ou “Evento”. Exemplo:
EventoFechar; EventoAbrir.
• Se for usar um evento que foi disparado no momento da ação ou depois da ação, utilize os
verbos no presente ou passado. Exemplo : EventoFechar; EventoFechou; EventoAbrir;
EventoAbriu.
• Para nomes muito grandes utilize abreviações. Exemplo : HTML (abreviação de Hyper Text
Marquet Language).
• Não use nomes idênticos no mesmo módulo ou procedimento, o ideal é utilizar nomes
completamente diferentes em todo o programa.
11
No momento da codificação os comandos estiverem extensos demais, pode-se quebrar a linha em
diversas partes sem gerar erros de execução. Utilize o “Caracter de continuação de Linha” ( _ ) após
um espaço simples, em seguida continuar a escrever o código em outra linha.. Exemplo :
Data1.RecordSource = _
"SELECT * FROM Titles, Publishers" _
& "WHERE Publishers.PubId = Titles.PubID" _
& "AND Publishers.State = 'CA'"
Assim, a linha de código fica mais fácil de ler na tela do seu computador, entretanto existe uma
limitação para o número de linhas.
Para combinar muitas linhas de código em uma única linha utilize dois pontos ( : ). Exemplo :
1. Parênteses : Use parênteses para criar um procedimento ou função. Exemplo : Sub Main ( ).
2. Separadores ( : ) : Os dois pontos ( : ) são usados para separar blocos de
código na mesma linha. Exemplo : Text1.Text = "Olá" : Vermelho = 255 :
Text1.BackColor = Vermelho
3. Concatenação : Para combinar duas variáveis Strings, utilize o operador de concatenação &.
Exemplo :
Var1 = "10.01"
Var2 = 11
Result = Var1 + Var2 ' Result = 21.01
Result = Var1 & Var2 ' Result = 10.0111
Não use o operador “ + “ para concatenar duas string, pois pode gerar erros. Observe os
resultados do exemplo acima.
4. Operador de acesso ( . ) : O ponto é utilizado para acessar funções, métodos ou propriedades
de uma classe ou objeto. Exemplo : MyForm.Text = "This is my form"
5. Operador de acesso ( ! ) : A exclamação também é utilizada para acessar métodos ou
propriedades somente de algumas classes ou estruturas. Exemplo :
RS.Fields!CustomerID.Value = txtCustomerID.Text
6. Caracter de declaração de tipos de dados ( ! ) : O ponto de exclamação também pode ser
utilizado para declarar variáveis do tipo Single. Exemplo : Var = 1234578!
Para cada linha de código, pode-se criar um comentário explicando o significado do procedimento,
este tipo de linha é ignorado pelo compilador. Utilize o símbolo de comentário ( ‘ ) para ativar o
comentário. Exemplo :
12
A Microsoft recomenda criar comentários para cada seção de código dessa forma :
1. Propósito : Inclua esse tópico no comentário, para identificar qual a descrição ou tarefa do
código em questão.
2. Requisitos : Inclua esse tópico no comentário, para identificar quais variáveis, objetos,
classes e outros elementos utilizados no código em questão.
3. Efeito : Inclua esse tópico para identificar quais variáveis, objetos, classes e outros elementos
que serão afetados pelo código em questão.
4. Argumentos : Inc.ua esse tópico para explicar os argumentos exigidos pelo código em
questão.
5. Retorno : Inclua esse tópico para identificar o valor de retorno desse código em questão.
Não se pode quebrar linhas em comentário, utilizando o caracter ( _ ). Pode-se utilizar o comando
REM para ativar comentários, entretanto esse procedimento requer mais espaço em memória que o
símbolo ( ‘ ), portanto utilize o símbolo somente.
No VB .NET existem limitações físicas, segundo a Microsoft, mas são tão altas que não há chances
de serem atingidas pelo desenvolvedor, a ponto de não serem nem documentadas oficialmente.
Quando se executa um programa, o compilador inicia a leitura do código fonte indistintamente até o
final. Entretanto esse comportamento pode ser alterado utilizando a Compilação Condicional.
A compilação condicional faz com que o compilador execute certos blocos de código enquanto
outros são ignorados. É útil quando se deseja usar comandos para certos tipos de Sistemas
operacionais em uso, ou utilizar dicionários para uma língua de um país, etc..
Para aplicar esse recurso use o comando de diretiva # if ... #Then ... # Else . Além disso pode-se criar
uma constante a nível de compilação usando o comando de diretiva #Const . Exemplo :
‘Cria uma compilação para a versão de um programa de língua Francesa ou Alemã, note
‘que FrenchVersion e GermanVersion são constantes predefinidas pelo VB.
#If FrenchVersion Then
' <código para a lingua francesa>.
#ElseIf GermanVersion Then
' <código para a lingua alemã>.
#Else
' <código para outras versões>.
#End If
13
2.7.1 – Criando Constantes de declaração Condicional
Constantes são variáveis que não podem ser alteradas. As constantes de declaração condicional são
variáveis que não podem ser alteradas e também não podem ser acessadas pelo código geral.
Pode-se criar constantes com caixa de diálogos de propriedades, por linha de comando ou por
comandos em código. Para criar constantes condicionais por comandos em código, utilize #Const.
Exemplo :
No VB .NET há um recurso que permite ocultar ou expandir o código escrito no Editor de Códigos, é
semelhante ao Windows Explorer ao visualizar os diretórios e subdiretórios do sistema. Quando um
diretório possui subdiretórios, o sistema exibe um sinal de mais ( + ) ao lado do nome do diretório
corrente, informando que há outros elementos nele. Basta clicar sobre o ( + ) para visualizar os outros
elementos.
Assim funciona esse recurso, que pode ser aplicado usando a diretiva #Region. Exemplo :
Esse recurso torna fácil ler e administrar o código fonte do desenvolvedor. Note que não é possível
usar esse recurso quando criar Funções, e qualquer código ocultado ou expandido é lido
normalmente pelo compilador.
É necessário utilizar técnicas para aumentar a produtividade do programador Visual Basic .NET,
além de solucionar grande parte dos bugs dos programas. Além disso utilizando essas técnicas
consolidadas de programação, permite criar códigos de alta qualidade e permite seguir as regras de
criação de software das grandes companhias.
Rotinas ou Procedimentos
• Quando criar rotinas ou procedimentos, evite usar nomes confusos que não contribuem para
explicar o significado do procedimento. Como por exemplo : Sub AnalizeIsto ( ).
• Quando criar classes, evite citar nomes redundantes para as propriedades, métodos ou
funções dessa classe. Como por Exemplo : Livro.LivroTítulo use : Livro.Título
14
• Quando Nomear um método ou Função, dê o nome da ação respectiva. Exemplo :
CalculeRaízQuadrada( ) . Com todas as iniciais em maiúsculas.
Variáveis
• Quando nomear variáveis que armazenarão dados calculados, finalize o nome com a
identificação do cálculo utilizado. Como por exemplo : intSoma, intDiferença, intMax,
intMin, pode-se utilizar até o nome de funções do VB para criar os nomes. intSum,
intAvg, intIndex, etc...
• Use nomes complementares quando forem necessários na mesma operação, tais como Início
/ Fim, Mín / Max, Aberto / Fechado. Exemplo : intInício, intFim, intMín, intMax.
• Para nomear variáveis utilize o primeira palavra em minúsculas e as restantes em
maiúsculas. Exemplo : documentoFormatoIndexado., ou utilize a notação húngara *.
• Para variáveis do tipo Boolean pode utilizar a palavra É, Esta ( Is) para designar se a variável
está na condição True ou False. Exemplo : ArquivoEstáAberto, ou FileIsOpen
• Muitos programadores utilizam a palavra Flag para nomear suas variáveis, entretanto é
preferível substituir a palavra Flag por outro nome que descreva melhor a variável. Exemplo:
ao invés de documentoFlag , use documentoFormatoIndexado.
• Para variáveis utilizadas em loops, dê nomes simples como i, j, x, etc...
• Utilize sempre constantes nomeadas para efetuar loops e outras condições de teste. Como
por exemplo : ao invés de For i = 1 to 7 utilize For i = 1 to intContadorIndexado,
onde intContadorIndexado é uma constante nomeada de valor 7.
* Uma notação especialmente popular é a notação húngara. Ela costuma ser usada na programação
em Windows e no OS/2. No caso da notação húngara, pode-se antecer uma variável String com “str”,
uma variável Integer com “int” , um ponteiro como “p”, funções com “fn”, handles com “h” e assim
por diante. A regra é compor o nome da variável utilizando a abreviação das primeiras letras do
controle, tipo de dados ou uma combinação de suas primeiras letras com um nome de identificação
individual.
A notação húngara foi desenvolvida por um programador da Microsoft chamado Charles Simonyi.
Nos velhos tempos da Microsoft, Charles ficou famoso por dar rasantes de helicópteros nos
piqueniques da empresa.
15
Data-bound combo box dbcbo dbcboLanguage
Data-bound grid dbgrd dbgrdQueryResult
Data-bound list box dblst dblstJobType
Data combo dbc dbcAuthor
Data grid dgd dgdTitles
Data list dbl dblPublisher
Data repeater drp drpLocation
Date picker dtp dtpPublished
Directory list box dir dirSource
Drive list box drv drvTarget
File list box fil filSource
Flat scroll bar fsb fsbMove
Form frm frmEntry
Frame fra fraLanguage
Gauge gau gauStatus
Graph gra graRevenue
Grid grd grdPrices
Hierarchical flexgrid flex flexOrders
Horizontal scroll bar hsb hsbVolume
Image img imgIcon
Image combo imgcbo imgcboProduct
ImageList ils ilsAllIcons
Label lbl lblHelpMessage
Lightweight check box lwchk lwchkArchive
Lightweight combo box lwcbo lwcboGerman
Lightweight command button lwcmd lwcmdRemove
Lightweight frame lwfra lwfraSaveOptions
Lightweight horizontal scroll bar lwhsb lwhsbVolume
Lightweight list box lwlst lwlstCostCenters
Lightweight option button lwopt lwoptIncomeLevel
Lightweight text box lwtxt lwoptStreet
16
Lightweight vertical scroll bar lwvsb lwvsbYear
Line lin linVertical
List box lst lstPolicyCodes
ListView lvw lvwHeadings
MAPI message mpm mpmSentMessage
MAPI session mps mpsSession
MCI mci mciVideo
Menu mnu mnuFileOpen
Month view mvw mvwPeriod
MS Chart ch chSalesbyRegion
MS Flex grid msg msgClients
MS Tab mst mstFirst
OLE container ole oleWorksheet
Option button opt optGender
Picture box pic picVGA
Picture clip clp clpToolbar
ProgressBar prg prgLoadFile
Remote Data rd rdTitles
RichTextBox rtf rtfReport
Shape shp shpCircle
Slider sld sldScale
Spin spn spnPages
StatusBar sta staDateTime
SysInfo sys sysMonitor
TabStrip tab tabOptions
Text box txt txtLastName
Timer tmr tmrAlarm
Toolbar tlb tlbActions
TreeView tre treOrganization
UpDown upd updDirection
Vertical scroll bar vsb vsbRate
17
Lista de nomes de Menus onde a regra é criar um prefino Mnu + Nome do Menu utilizado :
A Microsoft recomenda utilizar uma codificação modular, isto significa que se deve utilizar
variáveis, constantes, controles agrupados dentro de um procedimento que execute uma tarefa única
em um formulário simples. Por exemplo, para acionar uma caixa de diálogo Abrir, devemos colocar
todas as variáveis, controles e flags necessários agrupados em um único botão ou menu “Abrir” que
execute a tarefa de acionar essa Caixa de diálogo, uma vez terminado a execução da tarefa todas as
variáveis e controles são finalizados.
Lista de sugestão de escopo de variáveis (esses prefixos eram muito utilizados em versões anteriores
do Visual Basic, entretanto com a nova formulação da linguagem, essa terminologia quase não se usa
mais) :
Global g gstrUserName
Module-level m mblnCalcInProgress
Para se formar um nome de constante adequadamente, a regra é utilizar o prefixo do escopo acima +
o prefixo do tipo de dados + as letras iniciais maiúsculas do significado/propósito da constante,
exemplo:
Use os seguintes prefixos para indicar o tipo de dados da variável (esses prefixos eram muito
utilizados em versões anteriores do Visual Basic, entretanto com a nova formulação da linguagem,
essa terminologia quase não se usa mais):
18
Collection object col colWidgets
Decimal dec decRevenue
Date (Time) dtm dtmStart
Double dbl dblTolerance
Error err errOrderNum
Integer int intQuantity
Long lng lngDistance
Object obj objCurrent
Single sng sngAverage
String str strFName
Compound-defined type cdt cdtEmployee
Os nomes de variáveis de tipos definidos pelo usuário (tipos de dados compostos) podem ser
definidos com o prefixo “cdt” , assim cdt + nome da variável / combinação das tres primeiras letras ,
exemplo :
Tabelas
• Quando nomear tabelas use nomes sempre no singular. Exemplo : ao invés de tabela Alunos
use tabela Aluno.
• Quando nomear campos em tabelas, evite repetir o nome da tabela no Campo. Exemplo : ao
invés do nome do Campo AlunoEndereço utilize o nome Endereço.
• Não utilize o Tipo de Dados do campo para compor o seu nome.
Comentários
• Quando modificar o código fonte, coloque sempre a data da última modificação.
• No início de cada rotina, coloque os comentários no formato Propósito, Descrição,
Parâmetros, etc.. .( Ver item 3.5).
19
• Evite criar comentários no final de linha, pois fica mais difícil de ler. Se for imperativo,
coloque com uma tabulação padrão para todos os comentários desse tipo.
• Evite asteriscos e outros caracteres para criar o comentário, utilize somente espaços.
• Apague qualquer comentário improdutivo no código.
• Utilize palavras completas no Comentário, evite portanto abreviações e símbolos outros.
• Crie comentário para todo o código não óbvio.
• Explique o que consiste o loop e outros blocos de código.
Formato
• Utilize sempre o mesmo tipo de formatação para o código escrito. Isso inclui o tamanho da
letra, o tipo da letra, o espaçamento da letra, a cor da letra, etc..
• Utilize sempre parênteses , chaves e outros, para agrupar conjuntos de códigos para a mesma
finalidade. Exempo if (x >5 and x<10) then ...
• Crie uma tabulação padrão que torne consistente o código para cada bloco dentro de
procedimentos, loops, funções e etc...
• Evite combinar muitas linhas de código em uma linha única , utilizando o separador ( : ).
Exemplo : x = 350 : intContador = 4 : ArquivoEstáAberto = true
• Quando escrever comandos em SQL, utilize letras maiúsculas para palavras chaves SQL e
somente iniciais maiúsculas para Tabelas, colunas e Visões.
• Divida um código complexo em pedaços menores, podendo ser em módulos ou arquivos
separados
• Coloque a Cláusula SQL separados das linhas de comando para facilitar a leitura e edição do
código. Exemplo :
SELECT FirstName, LastName
FROM Customers
WHERE State = 'WA'
Palavras-Chaves (KeyWords) – São palavras reservadas da linguagem para construir uma estrutura
de comandos, e não podem ser usadas individualmente.
Comandos (Statements) – São instruções completas que fazem sentido ao compilador e podem
conter palavras chaves, operadores, constantes, expressões. Os comandos são divididos em duas
categorias :
Expressões – São séries de elementos que representam valores, separados por operadores que
resultam em outro valor. Utilizam de operadores de comparação para comparar dois valores; utilizam
operadores matemáticos para efetuar operações entre dois ou mais valores; utilizam de elementos
Booleanos para fazer comparações e parênteses para alterar a ordem de cálculos.
A Microsoft não reconheceu os Comandos de atribuição como uma terceira categoria, mas incluiu
na documentação como todos aqueles que utilizam operadores de atribuição.
20
Para declarar elementos para uso no código utiliza-se Comandos de declaração ou Palavras-Chaves.
O elemento declarado fica retido na memória do computador sendo gerenciado diretamente pela
tecnologia .NET Framework.
Os elementos declarados no código podem ser constantes, variáveis, objetos, classes, enumerações,
estruturas, propriedades, métodos, funções, eventos, interfaces, delegates (delegar).
O VB ignora letras maiúsculas e minúsculas quando se referir a elementos declarados, portanto pode-
se usar MinhaVariável quanto minhavariável.
1 – Variáveis
Uma variável é um espaço reservado dentro da memória para armazenar valores desconhecidos.
Diferentemente de um ponteiro que representa o local onde ela está endereçada.
O comando Option Explicit obriga que todas as variáveis sejam declaradas antes do uso.
2 – Comandos de Declaração
Os comandos de declaração são Dim e Const. As palavras chaves (Keywords) são Private, Public,
Shared, Protected, Friend e Static. Exemplo :
Private I As Integer
Dim Amount As Double
Static YourName As String
Public BillsPaid As Decimal
Const Modulus As Single = 4.17825 ‘Esse valor não pode ser alterado.
Public I, J, K As Integer ' Declara três variáveis inteiras.
Dim FirstName, MiddleName, LastName As String ' Declara três variáveis string.
Private S, SArray() As Short ' Uma variável Shor e uma variável de matriz.
Friend B1, B2 As Byte, C1, C2 As Char ' Duas variáveis Byte e duas variáveis Char.
O comando Dim é semelhante as palavras chaves Private e Public. E pode ser usado em
procedimentos, módulos, classes , blocos e estruturas, mas só podem ser acessadas no código que
foram declaradas. A diferença entre Private, Public e Dim é que as duas primeiras permitem ou não
21
que essa variável fique disponível a outros blocos de código, portanto são também chamados de
Modificadores de Acesso.
Alguns autores até recomendam não usar o Comando Dim por se tratar de um declarador pouco
expressivo.
A palavra chave Shared é um modificador de acesso que declara variáveis em classes, e permitem
que outros códigos acessem essa variável sem fazer uma referência a classe.
A palavra chave Static é um modificador de acesso e declara variáveis em todos os blocos de código
, exceto Classes e Módulos. Variáveis declaradas com Static retém o último valor na memória
mesmo quando o procedimento em que foi declarado é encerrado.
O Comando Const declara variáveis que não podem ser alteradas, e são utilizadas em todos os blocos
de código, entretanto a variável constante fica disponível somente ao código em que foi declarada.
A palavra chave Protected declara variáveis somente dentro de Classes. Variáveis declaradas com
protected só podem ser acessadas dentro da classe que a declarou ou de classes derivadas.
A palavra chave Friend declara variáveis em todos os blocos de código, exceto procedimentos.
Variáveis declaradas com Friend podem ser acessadas por todo o programa.
3 – Tipos de Dados
Para organizar como as variáveis gravam informações na memória, foram criados tipos de dados
elementares, que podem ser numéricos ou caracteres.
Os tipos de dados numéricos podem ser integrais (números inteiros) e não integrais (números
decimais fracionários). Os números inteiros são mais rápidos em processamento que os não
integrais.
Para cada tipo de Dados há uma faixa máxima de informações que podem ser gravados, além disso
certos tipos de dados podem ser sinalizados ou não sinalizados, isto significa que a faixa de
informações podem variar de números negativos até números positivos.
22
+/-0.0000000000000000000000000001 (+/-1E-28).
Double System.Double 8 bytes -1.79769313486231570E+308 à
(double-ponto -4.94065645841246544E-324 negativos; e
flutuante) 4.94065645841246544E-324 à
1.79769313486231570E+308 positivos.
Integer System.Int32 4 bytes -2,147,483,648 à 2,147,483,647.
Long System.Int64 8 bytes -9,223,372,036,854,775,808 à
(long integer) 9,223,372,036,854,775,807.
Object System.Object (classe) 4 bytes Qualquer tipo de dados..
Short System.Int16 2 bytes -32,768 à 32,767.
Single System.Single 4 bytes -3.4028235E+38 à -1.401298E-45 negativos; e
(single-ponto 1.401298E-45 à 3.4028235E+38 positivos.
flutuante)
String System.String (class) Depende do 0 até 2 bilhões de caracteres Unicode.
sistema
User-Defined (herda de Depende do Determinado pela faixa de cada tipo de dados usado na
Type System.ValueType) sistema estrutura
(estrutura)
• Tipo Valor – Quando a variável grava os dados dentro da memória. Assim enquadram-se
todos os tipos de dados numéricos, Boolean, Char, Date, Estruturas e Enumerações.
• Tipo Referência – Quando o sistema aponta para um endereço de memória onde está os
dados. Assim enquadram-se os tipos de dados String, Matrizes, Classes e Forms (Janelas).
A partir do VB .NET cada tipo de dado listado acima, é implementado como uma estrutura e Classe
da tecnologia .NET Framework. Isto significa que cada tipo de dado tem suas próprias funções e
métodos internos.
Basta verificar na coluna Common language runtime (CLR) qual classe pertence o tipo de dado
elementar.
Exemplo :
strTeste.Trim ( )
intTeste2.ToString ( )
No Exemplo acima, foi declarado uma variável do tipo String, e foi invocada a função Trim que
remove os espaços em seu conteúdo. Em seguida a variável intTeste2 foi declarada como um tipo de
dados Inteiro da classe .NET Framework, invocando a função ToString que converte os dados para
string.
Outra forma de declarar variáveis, é forçar a variável para tornar-se de um tipo utilizando os
“caracteres de tipo”. Veja a tabela abaixo:
Por outro lado, uma variável declarada dentro de um bloco de código, sua vida útil é igual ao tempo
que o procedimento estiver em execução. Assim quando o procedimento termina, a variável finda
sua vida útil e a memória é limpa e fica disponível novamente ao Sistema Operacional.
Quando uma variável é declarada com a palavra chave Shared, sua vida útil é extendida até quando
o aplicativo estiver em uso.
Quando uma variável é declarada com a palavra chave Static, sua vida útil é extendida entre
procedimentos que estiver em uso.
5 – Escopo
O Escopo de uma variável é a seção de um aplicativo que pode ver e manipular uma variável. Deste
modo, uma variável declarada em um procedimento, só pode ser manipulada nesse procedimento, as
outras seções ou blocos de código não podem ver nem manipular essa variável.
Escopo de Bloco – A variável fica disponível somente no bloco de código em que foi declarada.
Escopo de Procedimento – A variável fica disponível somente no procedimento que foi declarada.
Escopo de Módulo – A variável fica disponível para todo o código do módulo, classe ou estrutura
que foi declarada.
Escopo de EspaçoNomeado (NameSpace) – A variável fica disponível para todo o código desse
Espaço Nomeado.
6 – Acessibilidade
Acessibilidade é a permissão que uma variável poderá ser acessada ou manipulada. Para definir sua
acessibilidade usa-se as palavras chaves : Public, Private, Friend, Protected, Protected Friend.
Pode-se criar uma variável com escopo de Módulo, mas declarada com private, e nenhum outro
bloco de código poderá ver e manipular essa variável.
7 – Nomes Ambíguos
Quando se declara elementos, o Compilador do VB procura a referência a este nome na declaração.
Se houver mais de um elemento com o mesmo nome, o Compilador utiliza o elemento que estiver no
mesmo Escopo. Exemplo :
24
Module Mod1
Public Sub Perform() ' A palavra Chave Public permite acesso de outros procedimentos.
' ...
End Module
Module Mod2
Public Sub Perform() ' Pode ser diferente do cálculo executado em Perform( ) do Mod1.
' ...
Perform() ' Chama somente Perform( ) do Mod2 que é o modulo ativo (mesmo escopo).
Mod1.Perform() ' Chama Perfomr( ) do Mod1.
End Module
Module Mod3
' ...
Mod1.Perform() ' Chama Perform( ) do Mod1.
Perform() ' Chama Perform( ) que é um nome ambíguo e portanto gera um erro.
End Module
O Exemplo acima usa 3 Módulos, Mod1, Mod2 e Mod3. O módulo Mod1 possui um procedimento
declarado como Público chamado Perform( ) e portanto está disponível para acesso por outros
procedimentos. O módulo Mod2 possui outro procedimento declarado como Público também
chamado Perform( ), também disponível para acesso por todos os outros procedimentos. E
finalmente o módulo Mod3 que não possui nenhum procedimento declarado.
Note que tanto Mod1 quanto Mod2 têm um mesmo nome de procedimento Perform( ) (Nome
ambíguo). Quando Mod2 chama esse procedimento, o compilador procura o elemento declarado no
mesmo Escopo, isto é Perform( ) declarado no módulo ativo Mod2. Em seguida, quando Mod2
utiliza Perform( ) declarado em Mod1, utiliza uma descrição mais completa do lugar, informando ao
compilador onde deverá procurar a referência do elemento. Neste caso houve uma qualificação do
nome, e portanto não gera erros de execução.
Quando Mod3 utiliza Perform( ) declarado em Mod1, utiliza uma descrição mais completa do lugar
onde o compilador deverá procurar a referência do elemento.
Quando Mod3 utiliza Perform( ) sem qualificar seu nome, o compilador encontra o procedimento em
Mod1 e Mod2 portanto não sabe qual utilizar, gerando erro de execução.
No Exemplo acima, foi criado uma variável de referência a classe Class1, em seguida invocou-se o
método SomeSub( ). Não é permitido usar Class1.SomeSub( ) diretamente, pois nesse caso gera
erros de execução.
25
No VB .NET há formas de tratar elementos ambíguos, utilizando a técnica de ocultar elementos,
também conhecido como Shadow. Com Shadow um elemento fica ocultado de outro elemento com
mesmo nome além de não ficar disponível.
Module Mod3
Public Num As Integer ' Variável a nível de módulo.
Sub Show()
Dim Num As Integer ' Variável Local
Num = 2 'Variável Local agora tem o valor 2.
MsgBox(CStr(Mod3.Num)) ' Exibe o número 0.
End Sub
Sub UseModuleLevelNum()
Num = 1 ' Atribui 1 à Mod3.Num
' ...
Show() ' Chama Show, que exibe o valor da Variável de módulo Num, que agora é 1
End Sub
End Module
No exemplo acima, Mod3 tem uma variável a nível de módulo Num, e dois procedimentos
Show( ) e UseModuleLevelNum( ). No procedimento Show( ) foi declarada uma variável
local ambígua a Num.
2. Shadowing através de Herança – Quando uma classe é derivada de outra, pode-se ocultar
(Shadow) o elemento ambíguo existente na classe básica, utilizando a palavra chave
Shadow. Não se deve confundir Shadow (Ocultar) com Override (Substituir), que será
discutido mais tarde.
Exemplo :
26
Dim DObj As DervCls = New DervCls() ' Acessa através da classe derivada.
Public Sub ShowZ()
MsgBox("Classe básica: " & BObj.Z) ' exibe o número 100.
MsgBox("Classe derivada: " & DObj.Z) ' exibe a string "*".
End Sub
End Class
No exemplo acima, há três classes : BaseCLS que é classe básica e DervCLS que é a classe
derivada, e finalmente a Classe UseClasses que utiliza as duas primeiras. A classe básica
possui uma variável numérica pública Z que pode ser acessada por todos os códigos que
utilizam essa classe. A Classe Derivada possui outra variável Z string mas configurada com a
palavra chave Shadows que oculta a variável numérica da classe básica.
UseClasses faz referência as duas classes básica e derivada que muda o valor de cada
variável. Note que a referência de BObj é BaseCls por isso a variável numérica é utilizada
pelo compilador, enquanto que DObj, a variável string é utilizada pelo compilador.
Esta seção tem por objetivo estudar os tipos de dados fundamentais e apresentar um novo tipo de
dado composto, além de outros recursos de programação aplicados aos tipos de dados.
O VB .NET, por default, obriga a declaração de todos os elementos antes de usá-los no código.
Exemplo :
Se não for declarado o elemento no código, o compilador acusa o problema e gera erro. Este tipo de
recurso chama-se Declaração Explícita. Para desligar esse recurso utiliza-se o comando Option
Explicit Off.
Toda vez que o compilador encontrar a declaração Option Explicit Off, qualquer variável não
declarada em código irá ser considerada do tipo Object, entretanto esse tipo de comportamento do
compilador gera potenciais erros de execução além de gerar um aplicativo de desempenho ruim.
É recomendável utilizar em todos os códigos fontes o comando Option Explicit On para obrigar o
compilador varrer todas as variáveis não declaradas.
Quando todas as variáveis são declaradas com o tipo de dados em Option Explicit On, diz-se que os
elementos são Altamente tipificados (Strong Typing), que além de aumentar a velocidade do
aplicativo, se beneficia dos recursos do editor de códigos do Visual Studio, como por exemplo :
27
As variáveis do tipo Short podem guardar valores de 16 bits (2 bytes). É o menor tipo de dados
numérico disponível.
As normas aplicadas ao tipo de dados Integer logo abaixo, se aplicam ao tipo de dados Short.
Exemplo :
MeuNúmero = 32767
NossoNúmero = 32768 ‘O VB exibe uma mensagem “NaM Não é um nùmero”
No exemplo acima há duas variáveis declaradas do tipo Short (int16 é a mesma coisa que Short), a
primeira variável recebeu o valor máximo de armazenamento, enquanto que a segunda recebeu um
valor superior a capacidade de armazenamento. O VB acusa o erro exibindo uma mensagem de erro
na compilação “Existem erros, deseja continuar?“.
Qualquer tipo de dados numérico exige maior processamento do sistema , assim é necessário definir
o tipo adequadamente antes de usar. O tipo Integer armazena dados em 16-bit (2 byte) dentro da
faixa especificada acima, podendo ser utilizada para criar um enumerador (veja posteriormente).
VariávelInteger = 1234
Qualquer valor digitado entre aspas ( “ “ ) é uma string por definição, entretanto o VB ativa uma
interpretação correta para o tipo de dados da variável. Veja abaixo :
VariávelInteger = “1234”
O VB não se incomoda com aspas, já que a variável é do tipo numérica, podendo até efetuar
operações matemáticas corretamente, entretanto se houvesse um caractere diferente de número, o
sistema geraria um erro de Type Mismatch. Como no exemplo :
Pode-se utilizar um separador de precedência “( ) “ para atribuir o valor numérico a uma variável
integer sem alterar a interpretação do VB. Exemplo :
VariávelInteger = (1234)
Embora o parênteses não seja um caractere numérico, ele possui um significado de ativar a
precedência de primeiro plano em cálculos do compilador, pois desta forma não interfere na
interpretação do compilador VB. Entretanto quando se combina aspas + parênteses na atribuição de
um valor numérico, o resultado é ligeiramente diferente :
VariávelInteger = “(1234)”
Msgbox VariávelInteger
28
No exemplo acima, a VariávelInteger terá um valo negativo –1234 exibido na caixa de mensagem
Msgbox. A combinação de aspas e parênteses “( )” troca o sinal de um valor numérico positivo,
transformando-o em negativo. Essa funcionalidade foi inserida neste contexto como simples
curiosidade.
Conclui-se que um parênteses e aspas podem criar uma interpretação diferente no compilador do VB
quando atribuirmos valores a variáveis Integer, portanto devemos nos ater sempre as formas mais
simples e corretas de programação, não devemos portanto “inventar” coisas novas para o sistema
“descobrir” e que poderá levar a resultados imprevisíveis.
Uma variável do tipo Integer, quando não devidamente inicializada com um valor atribuído, tem
como Default o valor zero (0) , assim por exemplo, se um desenvolvedor esquecesse de atribuir um
valor a uma variável Integer, esse valor seria Zero (0) devido a natureza do tipo de dados Integer,
assim é completamente diferente de uma variável String vazia “”.
Exemplo :
MeuInteiro = 1234
NossoInteiro = 1234
Os tipos de dados Long são armazenados em 32–bits (4 byte), que irremediavelmente necessitam de
mais memória do sistema. Todas as observações referentes ao tipo de dados integer, se aplicam ao
tipo de dados Long, com uma ressalva na capacidade de faixa de dados que este suporta.
Exemplo :
MeuLong = 10
MsgBox(MeuLong.MaxValue)
MsgBox(MeuLong)
No exemplo acima, foi declarado uma variável do tipo Long (ou Int64) atribuindo o valor 10. Em
seguida foi utilizada uma função interna dessa classe que retorna o valor máximo de armazenamento
desse tipo de dados.
Observe que todos os tipos de dados possuem funções específicas, pois fazem parte de classes da
tecnologia .NET Framework.
Os tipos de dados Double armazenam informações em 64-bits (8 byte) e são especialmente utilizados
para cálculos precisos com números decimais. Os tipo de dados Single armazenam informações em
32-bits (4-bite). Todas as observações referentes ao tipo de dados integer se aplicam aos dados
Double e Single
VariávelDouble = 12.123456789 ‘O grande benefício deste tipo de dados são as casas decimais e
29
‘sua precisão nos cálculos.
Note porém que o VB somente aceita o separador decimal ponto ( . ) ao invés da vírgula, veja
explicações no tipo de dados Decimal logo mais adiante.
O tipo de dados Byte armazenam informações em 8-bit (1-byte), e são utilizados para conter dados
binários. Pode-se observar que o tipo de dados Byte é também referenciado em banco de dados, onde
é semelhante ao tipo de dados SmallInt em SGBD SQL Server.
Como um exemplo de utilização de dados binários é copiar o conteúdo de um campo de dados no
formato de imagem binária (*.bmp, *.jpg, etc) para outro campo de dados :
No fragmento de código acima, a variável MinhaFoto foi declarada explicitamente como Byte, e foi
atribuída a ela, o campo “Foto” de um objeto de banco de dados Recordset. Assim o conteúdo
binário dessa foto foi armazenada no tipo de dados Byte, que pode ser transferida para outro campo
do banco de dados.
O tipo de dados Byte quando não devidamente inicializado pelo desenvolvedor, terá sempre como
valor Default o zero (0).
Um tipo de dados Boolean armazena dois valores possíveis : Verdadeiro (-1) ou Falso (0) em
números de 16-bit (2-byte). O tipo de dados Booleano contém informações do tipo yes/no, on/off,
true/false. O valor padrão de uma variável do tipo de dados Boolean é sempre false (falso).
Os valores True e False são constantes pré-definidas no VB, que por outro lado poderiam ser
referenciadas como –1 e 0 respectivamente. O uso do tipo Boolean é tipico para operações de
comparação ou como retorno de funções específicas :
VariávelBoolean = ( 1 = 2)
A VariávelBoolean no exemplo acima, terá como resultado o valor 0 (False), decorrente de uma
comparação 1 = 2. Se a expressão de comparação fosse 2 = 2 , o valor de VariávelBoolean seria –1
(True).
Um outro exemplo de comparação entre strings para uso em tipos de dados boolean, confirma a
hipótese de que strings devem ser idênticas na sua construção, onde os caracteres maíusculos e
minúsculos fazem a diferença, neste caso específico de comparação :
Os dois elementos são strings semelhantes, entretanto não são idênticas, pois “CA” maiúsculo faz a
distinção com “Ca” , assim o resultado de VariávelBoolean será False.
As propriedades dos objetos, onde é informado true ou false (como por exemplo Enabled) são do tipo
Boolean. Como já foi dito , uma variável Boolean não inicializada com a atribuição , terá como
Padrão o valor False.
30
7 – Usando o tipo de dados Date
Os tipos de dados Date armazenam valores em números 64-bit (8-byte). Quando outros tipos de
dados são transformados para o tipo de dados Date, os números representados a esquerda do valor
decimal é a data, e os números representados a direita do valor decimal é o horário.
Sempre digite datas no formato mm/dd/aa para certificar-se que o sistema interpretará corretamente
os dados, em qualquer região.
Exemplo :
Portanto é necessário incluir o sinal # de forma a evitar uma interpretação indevida pelo compilador,
no caso de uma data em string “12/30/2001” o compilador não seria capaz de executar operações
com datas. Exemplo :
VariávelDate1= “12/30/2001”
VariávelDate2 =“11/30/2001”
MsgBox VariávelDate1 – VariávelDate2
O compilador do VB não gera mensagens de erro no caso do exemplo acima, mesmo que as
expressões não estejam devidamente configuradas com o sinal #, entretanto no momento de efetuar
operações com datas, o erro é iminente (Type mismatch).
VariávelDate1= #12/30/2001#
VariávelDate2 =#11/30/2001#
MsgBox VariávelDate1 – VariávelDate2
O tipo de dados Date também pode receber uma função intrínseca de data do VB, de forma a retornar
como resultado a data e o horário do sistema :
VariávelDate = Now ‘Função Now que retorna a data e hora atual do sistema
Msgbox VariávelDate
O resultado obtido na caixa de Mensagem será : 23/11/2001 18:46:13 como exemplo da construção
acima.
Para um cálculo envolvendo dias, bastaria acrescentar ou subtrair da expressão data um inteiro
simples, como mostrado abaixo :
VariávelDate = #12/01/2001#
Msgbox (VariávelDate –1 )
31
A mensagem final seria 01/11/2001, pois foi subtraído 1 dia da data originalmente atribuída a
VariávelDate. Deve-se observar, entretanto que para efetuar operações com datas mais eficiente, usa-
se as funções intrínsecas de datas do VB.
Note sempre que o formato atribuído é mm/dd/aa, caso essa regra não for obedecida, o VB trata de
corrigir o erro, invertendo a ordem das datas automaticamente. Entretanto, não se pode esperar um
bom resultado como por exemplo o dia 01/02/2001, o resultado final seria 02/01/2001 ao invés de
01/02/2001.
Os tipos de dados Decimal são armazenados em números de 128-bit (12-byte) inteiros a potência de
10, que representa o número de casas decimais. Esse tipo de dados, trabalha com números de grande
precisão.
Exemplo :
O tipo de dados Object armazena endereços de 32-bit (4-byte) dos objetos em referência. Esse tipo
de dados é suficientemente flexível para fazer referência a qualquer tipo de objeto reconhecido pelo
sistema. Essa definição de armazenar endereços assemelha-se a um conceito de ponteiros em C++,
guardando suas proporções. Exemplo :
A variável objDb foi declarada explicitamente como um objeto de banco de dados. Note, que a
declaração foi explicitamente genérica com object, de forma a piorar o desempenho do sistema,
como regra geral tente sempre declarar objetos como Classes a que pertencem ( discussão em
capítulos posteriores), uma forma de pesquisar a classe a que pertence o objeto é o Object Browser.
As variáveis do tipo Object podem ser tratadas do Tipo Valor ou do Tipo Referência já estudadas
anteriormente.
O Valor Nothing é usado para desassociar um objeto a variável. É recomendado desassociar (limpar
da memória) todas as variáveis Object que não forem mais utilizadas no programa. Exemplo :
32
No exemplo acima, foi utilizado uma variável de objeto que faz referência a um classe da tecnologia
.NET Framework para criar um instrumento de desenho, em seguida após o uso, foi desassociado a
variável do objeto, liberando a memória ao sistema.
O tipo de dados Char aceita somente caracteres Unicode 2 bytes (16 bit). Pode usar métodos como
IsDigit e IsPunctuation em variáveis desse tipo para determinar sua classificação.
Se o comando de verificação Option Strict estiver ligado, é preciso anexar o caracter Literal para que
o compilador identifique o tipo de variável corretamente. Exemplo
Option Strict On
' ...
Dim CharVar As Char
CharVar = "@" ' Não pode converter String em Char com Option Strict On.
CharVar = "@"C 'Assim pode
O tipo de dados String armazenam caracteres alfanuméricos e símbolos padrões de código ASCII ( 0
até 255) que representam todos os caracteres existentes, entretanto há de se mencionar que nem todos
os caracteres dentro dessa faixa são suportados pelo Windows. Há somente um tipo de strings :
Para atribuirmos valores em strings, basta colocarmos esse valor entre aspas “ “ , para ativar a
interpretação do VB para tipos de dados string. Assim :
VariávelString = “Carro”
No caso de uma abstenção no uso de aspas, o VB não interpreta a expressão como string, desde que
ela não ultrapasse uma palavra simples :
No exemplo acima, a primeira atribuição não ocorre porque o VB não interpreta a expressão como
uma string válida, assim a VariávelString terá string vazio “”. No último exemplo, o VB interpretou a
expressão como uma linha de comando de código ao compilador, e não como uma expressão String,
neste caso o VB gera uma mensagem de erro em execução ( Esperado final do comando !) , pois a
expressão não é uma palavra simples.
O VB tem uma sensibilidade especial para caracteres numéricos, de forma que não há necessidade de
utilizar-se de aspas para sua atribuição , conforme o exemplo :
VariávelString = 1234
Ou
Variável String = “1234”
Logicamente, não haverá maneira de efetuar qualquer operação matemática, o que pode ser feito é
uma concatenação de variáveis, com resultado de 12341234 (use sempre o operador & , veja em
33
capítulo posterior). Por outro lado, se fosse atribuído uma expressão 1234B sem aspas, o caractere
não numérico geraria um erro de execução.
De qualquer forma , é sempre necessário utilizar aspas “ “ para atribuirmos strings a variáveis string,
como uma forma correta de programação, mesmo que seja expressões com números.
Se uma variável String não for inicializada, isto é, se o desenvolvedor não atribuir nenhuma
expressão a ela, o seu valor será vazio “”.
No VB .NET há dois tipos de dados não numéricos mas que são produzidos por cálculos numéricos.
• Infinity – Qualquer cálculo que gera números infinitos. Por exemplo dividir um inteiro por
zero.
• NaN – Not a Number (Não é um Número). É qualquer resultado que não corresponde a
valores numéricos.
Exemplo1 :
msgbox (InfVar)
No exemplo acima, não há formas de dividir números inteiros por zero, portanto o resultado da tela
em msgbox é “+Infinito”. Observe que não há um tipo específico de dados que represente Infinity,
portanto é um recurso da linguagem do que propriamente um tipo de dados.
Exemplo2 :
Pode-se usar as funções IsInfinity e IsNaN para testar o resultado de cálculos matemáticos.
Exemplo:
34
MsgBox(“Encontrei um número muito grande. Não posso continuar”)
Else
MsgBox(“Encontrei um número muito pequeno. Não posso continuar”)
End If
Else
If result.IsNaN(result) Then
MsgBox(“Erro no cálculo”)
Else
MsgBox(“O resultado é “ & result.ToString)
End If
End If
Conversão é um processo que muda um tipo de valor de uma variável para outro tipo de valor. O
comportamento do compilador VB pode mudar quando a opção Option Strict estive ligada ou
desligada, por isso justifica-se estudar esse assunto.
meuInteiro = 32767
meuLongo = meuInteiro
meuLongo = 32767
meuInteiro = meuLongo
No exemplo 1 ocorreu uma conversão que alargou um valor de uma variável inteira para um valor
long. Enquanto que no exemplo 2 ocorreu um estreitamento de um valor de uma variável long para
um valor inteiro.
35
No exemplo 1 o compilador efetuou um conversão implícita, alargando um tipo de dados inteiro
para long sem qualquer interferência do desenvolvedor. No exemplo 2 o compilador também efetuou
uma conversão implícita estreitando um tipo de dados long para integer, pois a opção Option Strict
estava desligada (Option Strict Off).
O compilador efetua uma conversão explícita, quando o desenvolvedor usa comandos de Conversão
de modo a forçar uma conversão de um tipo de dados para outro, esse tipo de conversão é também
conhecida como Casting. Exemplo
meuInteiro = CInt(MeuLongo)
Uma conversão do tipo Narrowing explícita, isto é converter um valor maior para menor com uma
função de conversão do VB, pode gerar perdas nos dados. Uma conversão do tipo Widening
explícita, isto é converter um valor menor para maior com uma função de conversão do VB, pode
gerar perdas no arredondamento decimal de valores no caso de converter um dados do tipo Long
para um Decimal. Pois o tipo Decimal aceita grande quantidade de números após a vírgula enquanto
que Long não aceita números decimais.
A conversão de qualquer tipo de dados string para um tipo de dados numéricos é sempre do tipo
Narrowing. O operador de concatenação ( & ) também funciona como conversor implícito. Exemplo:
A função Val do VB .NET pode ser utilizado para conversão de strings. A função varre toda a string
até encontrar um dígito diferente quando termina o processo convertendo somente os números
encontrados. Exemplo :
Dim m As Integer
Esse comportamento pode ser alterado desligando o controle de verificação Option Strict Off. Deste
modo todas as variáveis podem ser usadas sem declaração anterior e o tipo de conversão (Narrowing)
pode ser feito implicitamente, isto é sem funções de conversão.
36
O compilador do VB considera alguns valores como default, como por exemplo qualquer valor
numérico desde que não seja muito alto é considerado Integer; qualquer valor com dígitos
decimais é considerado como Double; qualquer valor muito extenso é considerado Long, e
finalmente qualquer valor com True ou False é considerado Boolean. Assim quando houver erro
em atribuição de valores a constantes ou variáveis, basta forçar o valor da variável utilizando os
comandos de tipo de dados. Exemplo :
Muitos números usados em VB são decimais (base 10). Mas pode ocorrer o uso de números
hexadecimais (base 16) ou números octal (base 8). O Visual Basic representa nrs. Decimais com o
prefixo &H e octal com &O.
O computador pode trabalhar com qualquer número utilizado pelo sistema, entretanto o número
hexadecimal é utilizado em certas tarefas, como o sistema de cores, tela e principalmente as APIs do
Windows.
As estruturas de dados é uma forma de combinar diferentes tipos de dados para criar uma única
estrutura. Essa técnica é chamada de Tipo de Dados Compostos, pois permite criar tipos de dados
personalizados que eram conhecidos como User Defined Type UDT nas versões do VB 6.0.
Entretanto, como as estruturas permitem criar além de tipos de dados fundamentais, também
propriedades, métodos e eventos, as UDT foram aposentadas, e daqui por diante existirá somente as
Estruturas de Dados.
Para criar uma estrutura, inicie com o Comando Structure e finalize com End Structure. Dentro
desse bloco de código declare as variáveis normalmente. Exemplo :
37
Structure Empregado
Public Nome As String ' Nome do empregado.
Public NomeFamília As String ' Sobrenome da Família.
Public Telefone As Long ' Telefone do empregado.
Private Salário As Decimal ' Salário do empregado.
End Structure
No Exemplo acima, a estrutura foi criada com o nome de Empregado e possui variáveis públicas
(Acesso a todos os blocos de código) e privadas (Acesso não permitido a outros blocos de código).
Como opção, pode-se declarar uma estrutura como Public ou Private antes do comando Structure.
Depois de criar uma estrutura, deve-se criar uma variável e declará-la com o nome dessa estrutura,
em seguida utilize as propriedades e métodos dessa estrutura. Exemplo
As Matrizes (Arrays) são séries de variáveis, objetos, elementos ou controles que possuem o mesmo
nome e são diferenciados somente por um índice que os torna únicos para identificação. As variáveis
de mesmo nome são identificadas pelo seu índice único, que vão desde o índice mais baixo também
conhecido como LBound (lower bond) até o índice mais alto UBound (upper bond) , essas faixas
permitem que o VB evite criar matrizes maiores que o necessário. Todos os elementos de uma
matriz , devem ser de um único tipo de dados, entretanto se o tipo de dados for Object, é claro que os
dados armazenados nesta matriz podem ser string, números, datas, objetos e etc.
• Para se criar uma matriz pública, use o comando Public na seção de declaração.
• Para se criar uma matriz a nível de módulo (module-level) , use o comando Private na seção
de declaração.
• Para se criar uma matriz local (procedure-level), use o comando Dim, Static dentro de um
procedimento para declarar uma matriz.
• Pode-se utilizar matrizes dentro de classes utilizando os comandos Protected, Friend, Public,
Private e Dim.
As matrizes podem ser declaradas fixando os seus limites máximos com base na faixa do tipo de
dados Long ( -2,147,483,648 até 2,147,483,647). Exemplos :
No exemplo acima, a matriz MeuArray foi declarada com no máximo 14 elementos, entretanto o
limite inferior inclue o Zero (0), que é utilizado para efeito de contagem , portanto existe 15 slots
para a matriz. A segunda declaração comporta o máximo de slots possível.
As matrizes podem ser alocadas automaticamente pelo VB, de modo que o desenvolvedor não
precise determinar o limite máximo :
O Exemplo acima não especifica os limites da matriz , apenas sujeita o VB alocá-lo automaticamente
com parênteses ( ), essa matriz é conhecida como Matriz Dinâmica e o VB vai criar os limites até a
38
faixa máxima do tipo de dados Long. Esse procedimento é utilizado, quando o desenvolvedor não
sabe de antemão quais os limites da matriz.
Por outro lado , nos exemplos anteriores, a matriz foi alocada nos limites máximos, de forma que a
matriz resultante é conhecida como Matriz Estática , e só pode ser utilizado quando o desenvolvedor
tiver completa certeza dos limites da matriz a ser utilizada.
Matrizes Unidimensionais – Que possuem apenas uma dimensão de valores mínimo e máximo .
Como por exemplo :
O valor de MeuArray (1,1,1) = 10 ; o valor de MeuArray (2,3,4) = 240 de forma muito simples.
Entretanto o valor de MeuArray (2,3,1) = 60, o valor de MeuArray (1,2,2) = 90. De forma geral tem-
se :
Para se popular uma matriz, usa-se os índices apropriados juntamente com o tipo de dados
corretamente, a forma recomendada pela Microsoft é utilizar um Loop para manipular e popular as
matrizes.
MeuArray ( 1, 1) = “Olá 2”
MeuArray ( 1, 2) = “Olá 3”
MeuArray (1, 3) = “Olá 4”
-
-
Etc...
Importante, as matrizes necessitam de muita memória para armazenar seus valores, e a medida que
os valores limites aumentam , mais recursos do sistema é necessário. Além do mais, as matrizes
multidimensionais construídas com base no tipo de dados Object, são vorazes consumidores de
memória. As matrizes dinâmicas podem afetar o desempenho da execução do sistema.
Assim, quando declara-se uma matriz dinâmica na seção de módulo de um formulário, esta matriz
pode ser redimensionada de dentro de uma procedure. A lógica de programação do desenvolvedor
pode identificar os limites e dimensões da matriz, e em seguida redimensionar a matriz :
No exemplo acima, a matriz Matrix1 foi declarada explicitamente de forma dinâmica com o tipo de
dados numérica, e o procedimento CalcValueNow irá redimensionar os valores da matriz, para
economizar recursos de memória e do sistema, utilizando o comando ReDim para alocar 20 e 30
slots multidimensionais. O trabalho do procedimento CalcValueNow é identificar os limites da
matriz e redimensiona-los automaticamente.
Cada vez que Redim é acionado, os valores da matriz são limpos, assim os valores de tipos de dados
variants são convertidos para vazios, os valores são zerados para os tipos de dados integers , os
valores são limpos (strings de tamanho zero) para os tipos de dados string e os valores são
convertidos para Nothing (nenhum objeto) para os arrays de objetos. A representação abaixo mostra
como fica cada matriz após o uso de Redim:
40
A única forma de reter esses valores , aproveitando os valores antigos já criados, e aumentando
somente os slots para novos dados, utiliza-se o comando Preserve .
De forma geral , esse comando é útil quando se deseja preparar a matriz para novos dados, mesmo
que este esteja populado com valores anteriormente armazenados por procedimentos anteriores.
Entretanto pode-se mudar apenas o último limite máximo (UBound) da última dimensão de uma
matriz multidimensional, se tentarmos mudar um limite inferior (Lbound) ou de outra dimensão, um
erro de run time vai ocorrer.
O código acima, pode ser usado, pois acrescenta a última dimensão da matriz Matrix um (1) slot a
mais. Note que foi usado a função UBound para identificar o limite máximo da última dimensão (2).
Entretanto o código acima, não pode ser utilizado, pois a tentativa de acrescentar mais um slot para a
primeira dimensão, gera um erro de runtime.
Pode-se atribuir um conteúdo de uma matriz para outra, de duas formas : A primeira copia-se slot por
slot de cada matriz e atribui para outra matriz slot por slot, mas é mais eficiente utilizar a atribuição (
= ) para copiar uma matriz para outra :
Obviamente, deve-se obedecer regras para efetuar cópias de variáveis, caso contrário podem gerar
erros de compilação e de run-time :
As matrizes devem ter o mesmo tipo de dados, ou a variável que receber a cópia seja Object.
As matrizes devem ter o mesmo número de dimensões.
Os tipos de elementos de cada matriz devem ser compatíveis.
As matrizes só podem ser definidas com Base zero (0), isto é inicia-se no zero (0), assim um matriz
do tipo “MinhaMatriz(5) “ possui 6 slots vazios , pois o limite inferior é zero.
1 – Utilizando Matrizes
Pode-se declarar uma matriz e em seguida atribuir o valor, ou declarar e atribuir (inicializar) o valor
simultaneamente.
Exemplo 1 :
41
MinhaVariável (1) = 3456 ‘Atribui um número ao primeiro slot
MinhaVariável (2) = 3457 ‘Atribui outro número ao segundo slot
Exemplo 2 :
Dim MinhaVariável ( ) as single = New single ( ) {3456 , 3457 } ‘Declara e inicializa os valores
Observe que no exemplo 2, a matriz é inicializada como parte da sua declaração, e portanto deve
seguir as seguintes regras :
• Use sempre o sinal de igual ( = ) seguido pela palavra chave New com o tipo de dados da
matriz.
• Finalize sempre com chaves { } a atribuição de valores.
Exemplo 3 :
Dim Meu ( ) as Byte = New Byte ( ) ‘ Declaração errada pois falta chaves { }
Dim Minha ( ) as Byte = New Byte ( ) { } ‘ Declaração correta
No exemplo acima as duas declarações foram feitas sem valores iniciais, mas somente a segunda
declaração “Minha” é válida.
Exemplo 4:
Exemplo 5 :
No Exemplo 4 e 5, a matriz “Nossa” tem duas dimensões de zero até hum, com declarações e
atribuições válidas, observe que no exemplo 5 a sintaxe é diferente.
Após a palavra chave New Short, é obrigatório incluir o número de vírgulas correspondentes a
declarada na variável Nossa ( , ). Para atribuir os valores é obrigatório incluir chaves adicionais além
de vírgulas { {5,6} , {8,8}}.
Exemplo 6 :
42
Dim Tua () () As Byte = {New Byte() {5, 6}, New Byte() {7, 8}}
No exemplo 6, foi criado uma matriz contendo outra matriz. Este tipo de técnica é chamado de
matriz não retangular ou recortada (jagged) e está disponível somente no VB .Net.
A matriz não retangular (matriz de matriz) tem sintaxe diferente de uma matriz multidimensional. No
exemplo 6, a primeira matriz “Tua” foi inicializada com os valores 5 e 6 , enquanto que a segunda
matriz foi inicializada com 7 e 8.
Assim para utilizar o primeiro elemento da primeira matriz usa-se ( 0 ) e ( 0 ), para utilizar o segundo
elemento da primeira matriz usa-se (0) e (1). Para acessar o último elemento da última matriz do
exemplo, usa-se (1) e (1).
Usa-se uma matriz de matriz quando o desenvolvedor deseja combinar matrizes mas não se deseja
criar uma matriz bidimensional.
Exemplo 7
Número(0) =1 : Número(1) = 2
Letra(0) = “A” : Letra(1) = “B”
TudoJunto(0) = Número
TudoJunto(1) = Letra
No exemplo 7, criou-se uma matriz “TudoJunto” do tipo Objeto que aceita qualquer tipo de dados do
sistema, além de duas matrizes de tipos de dados diferentes entre si.
Observe que não foi atribuído valores para TudoJunto, mas sim recebeu como atribuição as outras
matrizes “Número” e “Letra”. Observe ainda, que este tipo de atribuição diminui o desempenho do
aplicativo.
Como já foi visto nos tópicos anteriores, todo o tipo de dados fundamental é uma cópia de classes da
tecnologia .Net Framework. Desta forma, as matrizes também herdam os recursos da classe
System.Array, oferecendo seus próprios métodos.
Exemplo 8 :
43
Dim Meu(1) as integer = New Integer ( ) {4,5}
No exemplo 8, foi declarado e inicializado a matriz “Meu”, em seguida foi invocado as Propriedades
da classe .Net que está embutida na matriz Meu.
A Propriedade Rank retorna o número de dimensões da Matriz, enquanto que a Propriedade Length
retorna o número de slots declarados na matriz. O Método Clear limpa o valor atribuído a um slot.
Observe que para utilizar as funções-membros da classe é necessário fazer a referência completa à
variável além do ponto . Meu.Rank.
2.11 – Objetos
O VB .Net foi projetado inteiramente para programação orientada a objeto (OOP), e todo o
desenvolvedor irá trabalhar com objetos. Objeto é uma pequena parte de código que engloba
funções, propriedades e métodos num único lugar, e não pode ser executado sozinho sem um
aplicativo principal. O processo que engloba funções, propriedades e métodos num único objeto é
chamado de Encapsulamento.
Classes e Objetos
Geralmente os objetos são escritos em forma de arquivos dll, e podem ser utilizados declarando
variáveis como referência a eles. Outro conceito importante é a diferença entre Classes e Objetos.
• Classes – É o protótipo de criação dos objetos, isto é o código fonte que contém
procedimentos, funções para a criação do Objeto. Cada objeto no VB .Net é uma classe,
basta fazer uma referência no programa para utilizar seus recursos.
• Objeto – É uma cópia, também conhecida de instância, de uma classe. Pode-se utilizar
quantos objetos desejar, uma vez criado a classe . Assim a Toolbox (Barra de ferramentas) do
VB .Net é uma coleção de classes, uma vez escolhido um controle e desenhado na janela, esta
classe se transforma em Objeto. As Janelas do VB .Net são classes e quando o aplicativo está
em execução (Run Time) o compilador cria uma cópia da classe e se transforma em Objeto.
Membros
NomeDoObjeto . NomeDoMembro
Text1.Caption = “Olá”
Para utilizar um Objeto, é preciso criar uma instância (Cópia) da Classe, em seguida basta utilizar os
Membros.
Exemplo:
MeuObjeto.Cantar
No Exemplo acima, foi criada uma cópia de uma classe chamada Class1 utilizando a palavra chave
as e New, em seguida utilizou-se do membro Cantar que executa um pseudo procedimento. Observe
que se omitir o comando New , a variável fica declarada e pronta para receber a cópia de uma classe,
mas efetivamente a variável não é criada e não recebe a atribuição.
Com o comando New, o compilador cria a variável e atribui a ela a cópia da classe.
Fontes de objetos
Com o VB .NET pode-se utilizar Objetos Externos tais como as ferramentas de edição de texto do
Microsoft Word, as fórmulas do Microsoft Excel, e tantos outros recursos do Office, Corel, AutoCad
e etc. Para isso basta criar uma referência a fonte Externa no menu do Visual Studio .NET.
Neste ultimo exemplo, o comando With … End With melhora o desempenho do código e torna mais
fácil a leitura do código para outro desenvolvedores.
Janelas (Forms)
As Janelas, também conhecidas como Forms, Window, etc, são objetos gráficos que fazem a
interface do usuário. No VB .NET as classes definem como as janelas serão exibidas e o que elas
farão. Quando um aplicativo está em execução e uma janela é exibida na tela, o VB .NET cria uma
instância (cópia) da Classe denominada Form.
Pode-se alterar o comportamento das janelas, ou criar novos procedimentos e métodos. Por exemplo,
para criar um procedimento (método) para a janela basta escrever o procedimento e declará-lo como
público . Exemplo
O Exemplo acima cria um procedimento público Som, que pode ser acessado por outras partes do
código. Exemplo :
Form1.Som ( )
No exemplo acima, foi criado uma instância da Janela para acessar o método Som ( ).
2.12 – Strings
Strings é um tipo de dados elementar que representa uma matriz de caracteres ( tipo de dados Char),
que aceita qualquer expressão desde que estejam entre aspas. Exemplo :
Para usar aspas na criação da string, é necessário criar uma dupla marcação de aspas. Exemplo
Toda string é imutável , isto significa que o seu valor não pode ser alterado uma vez que foi criado.
O que acontece é que, qualquer variável do tipo de dados String é um tipo Referência e portanto
aponta para a memória onde o valor está armazenado, uma vez que o valor é alterado por outra
string, essa variável é destruída e criada em seguida com a nova string. Exemplo :
No Exemplo acima a primeira linha do código cria uma instância (Cópia) da string e atribui um
valor. Na próxima linha, essa variável é destruída e uma nova cópia é criada e atribuída o novo valor
“Agora não quero mais”.
Todo tipo de dados é uma classe da tecnologia .Net Framework que oferece métodos da própria
classe. Além disso o VB .NET também oferece funções herdadas da própria linguagem, isto significa
que não é preciso fazer referência ou cópia da classe para poder usá-las. Exemplo :
No exemplo acima, a sintaxe é a mesma do antigo VB 6.0 onde a função é utilizada sem qualquer
referência a classe.
Além disso, no VB .NET pode-se utilizar métodos da própria classe String de duas formas
• Métodos Shared (Métodos Compartilhados) – Outra forma de usar um método sem fazer
referência ou cópia de classes. Basta colocar o nome da própria classe. Exemplo
O compilador trata o tipo de dados especial Nothing igual a string vazia “”, entretanto o compilador
não pode fazer operações com este string. Exemplo :
Pode-se comparar strings utilizado o método Compare da classe String, ou a função StrComp do
VB. Exemplo :
Dim m as string
Dim n as string
Dim resultado as integer
47
m = “Nosso”
n = “Meu”
Esse método retorna um número que indica o resultado da comparação, se o número for positivo
então a primeira string (m) é maior que a segunda string (n). Se o resultado for negativo, então a
segunda string (n) é maior que a primeira string (m), ao passo que se o resultado for zero, então as
duas strings são iguais.
É possível procurar Strings dentro da string, utilizando o índice da matriz ou procurando pela letra na
matriz. Pode-se também utilizar as funções InStr do VB. Exemplo :
Observe que Strings são matrizes de caracteres (Char) e portanto possui índices, a propriedade Char
é usada para retornar a letra da matriz informando o seu índice. No exemplo acima o índice 3
corresponde ao caracter D.
No exemplo acima, a propriedade IndexOf é utilizada para retornar o número do índice (posição do
caracter no string) com base no caractere informado. O caractere D está na posição 3 (índice).
É possível concatenar (combinar) duas ou mais strings, utilizando o método Concat ou os operadores
& , + do VB. Exemplo :
Uma das funções mais importantes para strings é Trim, que remove os espaços no texto. Usa-se a
função Trim do VB ou o método Trim da classe String para remover os espaços na string. Exemplo :
48
No exemplo acima, foram utilizados tanto as funções do VB quanto o método da classe String para
remover os espaços. Note que é possível eliminar somente os espaços iniciais com LTrim quanto os
espaços finais com RTrim. Exemplo:
Dim m As String
Dim a As String
m = "&&&&Caco&&&&&"
a = m.Trim("&")
Acima, o exemplo demonstra o uso de Trim para remover caracteres específicos na string.
Constantes são valores que nunca mudam, é um recurso da linguagem que utiliza nomes ao invés de
valores facilitando a leitura do código por outros desenvolvedores.
Constantes
Para criar uma constante declare uma variável com o comando Const, obedecendo as regras de
codificação e programação já estudadas anteriormente. Observe que se a opção Option Strict estiver
ligada (Option Strict On) então é obrigatório declarar explicitamente o tipo de dados da Constante.
Exemplo:
O exemplo acima declara a constante IdadeDoBrasil em 500 anos com escopo Público, isto é pode
ser acessada por outros blocos de código, e as constante IdadeDoMatusalém em 1500 anos tem
escopo local e não pode ser acessado por outros blocos de código. Observe que a opção Strict está
desligada por default, portanto não precisa especificar o tipo de dados da constante.
Option Strict On
No código acima, a opção requer declarar o tipo de dados das constantes. Observe, porém que todas
as constantes agora são Públicas e foram declaradas na mesma linha de código.
Há dois tipos de constantes no VB, as constantes definidas pelo usuário (User-Defined Constants)
e as constantes intrínsecas ou pré-definidas, isto é as constantes do próprio VB .NET.
49
• User-Defined Constants – As constantes definidas pelo usuário são todas as constantes
nomeadas criadas pelo programa do desenvolvedor, nos exemplos anteriores as constantes
foram criadas e definidas pelo usuário.
• Constantes intrínsecas ou pré-definidas - As constantes do VB são todas as constantes
embutidas na linguagem. Podem ser utilizadas em todas as partes do código e não precisam
ser declaradas.
As constantes definidas pela linguagem VB, podem ser examinadas no Object Browser do ambiente
de desenvolvimento Visual Studio .NET, veja no capítulo referente ao Ambiente de
Desenvolvimento Integrado do Visual Studio.
Exemplo de criação de constantes definidas pelo usuário utilizando constantes pré-definida pelo VB.
End Sub
No exemplo acima as duas constantes são Sim e Não e foram atribuídas os valores de vbYes e vbNo,
respectivamente 6 e 7. Observe que as constantes foram criadas dentro de procedimento local
(Evento clique de um botão), portanto não é permitido incluir comandos de declaração como por
exemplo Dim, Public, Private, etc..
Assim como as variáveis, as constantes devem ser coagidas a receber alguns tipos de dados de
valores muito altos, dependendo do estado da opção Option Strict, veja a explicação no capítulo
Elementos de Dados. Exemplo :
Option Strict Off ‘Opção ligada então e preciso coagir as constantes a receber os valores
Public Const DefaultInteger = 100 ' Default é Integer.
Public Const DefaultDouble = 54.3345612 ' Default é Double.
Public Const MyCharacter = "a"C ' Força a constante a ser do tipo Char.
Public Const MyDate = #01/15/01# ' constant do tipo Date.
Public Const MyTime = #1:15:59 AM# ‘idem acima
Public Const MyLong = 45L ' Força o tipo de dados Long.
Public Const MySingle = 45.55! ' Força o tipo de dados Single.
O compilador do VB considera alguns valores como default, como por exemplo qualquer valor
numérico desde que não seja muito alto é considerado Integer; qualquer valor com dígitos
decimais é considerado como Double; qualquer valor muito extenso é considerado Long, e
finalmente qualquer valor com True ou False é considerado Boolean. Assim quando houver erro
em atribuição de valores a constantes ou variáveis, basta forçar o valor da variável utilizando os
comandos de tipo de dados. No exemplo acima, todas as constantes estão declaradas corretamente,
portanto o compilador não gera erros em execução.
Exemplo :
50
No exemplo acima e conforme as definições acima, o valor 100000000000000000000 é considerado
Double (default) pelo compilador, e a variável myDecimal é do tipo Decimal. Mesmo que o tipo
Decimal suporte o valor acima descrito, ele não pode aceitar o tipo de dados Double (que é muito
maior), portanto o compilador gera um erro. A forma correta de utilização é :
Enumeradores
Exemplo :
Como Default, o valor da primeira constante do Enumerador Dias é zero (0), e os valores
subseqüentes são incrementados automaticamente com um (1), assim Segunda teria o valor 0, Terça
o valor 1, Quarta o valor 2 e etc. Pode-se ainda, atribuir explicitamente valores as constantes, usando
a operador de atribuição igual ( = ), mas certifique-se em não criar enumeradores com valores do
tipo ponto flutuante.
51
Para um correto uso de enumeradores, utiliza-se a estrutura hierárquica para acessar as constantes,
desta forma evita-se conflitos de referências, quando há enumeradores com constantes iguais :
Dias . Saturday
Assim como as constantes, os enumeradores podem ser tanto intrínsecos ao VB, isto é enumeradores
definidos pelo sistema VB, quanto enumeradores definidos pelo usuário. Por exemplo a função
MsgBox do VB possui as seguintes enumerações e constantes definidas pelo sistema :
Exemplo :
No exemplo acima, foi necessário nomear a classe MsgBoxStyle a que pertence as enumerações,
além disso foi possível combinar várias enumerações para criar a mensagem “Olá”.
2.14 – Operadores
52
Operadores são unidades de código que executam uma operação e retornam elementos como
resultado. Podem ocorrer operações aritméticas; operações de concatenação; operações de
comparação; operações lógicas.
Os operações de atribuição e os operadores gerais, entretanto podem não retornar elementos como
resultado, apenas executam operações gerais.
1. Operadores aritméticos
Dim X as integer
Dim Y as integer
Dim Z as double
2. Operadores de Comparação
Esses operadores comparam duas expressões e retornam um valor Boolean como resultado.
No primeiro exemplo o compilador usou um padrão de ordem de classificação para comparar duas
strings, o padrão especifica que 73 está em último lugar na ordem de classificação então a
comparação > é True. No segundo exemplo, as duas strings têm a mesma ordem de classificação e a
comparação é = , portanto o resultado é True. No terceiro exemplo, a string “aaa” tem um prefixo a
mais que “aa”e toda a string maior é classificado primeiro que a string menor, logo o resultado é
True.
Option Compare
O comando Option Compare indica ao compilador o padrão para comparar strings. O comando
possui esta sintaxe :
Option Compare Binary – (Default) O compilador reconhece o ordem de classificação dos caracteres
da seguinte forma :
A < B < E < Z < a < b < e < z < À < Ê < Ø < à < ê < ø
Option Compare Text – O compilador reconhece a ordem de classificação dos caracteres de forma
insensitiva, isto é não importa se os caracteres estão em maiúsculos ou minúsculos. Assim :
(A=a) < (À=à) < (B=b) < (E=e) < (Ê=ê) < (Ø=ø) < (Z=z)
Exemplo :
Dim x As MyClass
Dim y As New MyClass()
x=y
If x Is y Then
‘msgbox (“São iguais”)
end if
No exemplo acima foram criadas duas variáveis que são instâncias (cópias) da classe MyClass ( ),
em seguida foi atribuída a variável inicializada y para outra não inicializada x, neste caso é a mesma
54
cópia do objeto. O último comando executa um teste comparando o valor de uma com o valor de
outra, em caso afirmativo vai exibir uma mensagem “São Iguais”.
No exemplo acima, foram também criadas duas variáveis que são cópias da classe MyClass ( ),
observe porém que as cópias são do mesmo objeto, isto é MyClass, mas as instâncias (cópias) são
diferentes. A variável X criou uma cópia separada do objeto, pois utilizou o comando New, enquanto
que a variável Y criou outra cópia separada do mesmo objeto, pois também utilizou o comando New.
Dim x As Button
x = New Button()
If TypeOf x Is Control Then
' Continuação do programa.
No exemplo acima, o operador é chamado para verificar se a variável X é uma instância de uma
classe, neste caso o resultado é True.
3. Operadores de Concatenação
Os operadores de concatenação juntam duas strings em uma única string. Dois são os operadores de
concatenação : & , + .
O operador & foi especialmente criado para junções de variáveis do tipo string :
O operador + além de ser um operador aritmético, também pode ser usado para concatenar strings. O
compilador do VB tem comportamentos diferentes quando a opção Option Strict está ligada (on) ou
desligada (off).:
• Strict On – o compilador utiliza tanto & quanto + para concatenar variáveis strings da mesma
forma.
• Strict Off – o compilador utiliza + para fazer conversões implícitas entre diversos tipos,
enquanto que & não pode executar essas conversões.
Exemplo :
Option Strict On
' inicializa as variáveis de diferentes tipos.
55
var1 = "34"
var2 = 6
myNumber = var1 + var2 ' Gera um erro de compilação.
No último exemplo acima, o operador + faz uma conversão implícita de Var1 para integer, e o
resultado final é a soma de duas variáveis do tipo integer.
4. Operadores Lógicos
Os operadores lógicos comparam duas expressões do tipo verdadeiro ou false e retornam um valor
do tipo Boolean, além disso, os operadores lógicos também podem processar comparações em
Bitwise que comparam dois valores em formato binário (base 2).
Dentre os operadores acima, todos trabalham com dois operadores, mas somente Not trabalha com
um operador (unário). Exemplos
Dim x As Boolean
x = Not 23 > 12 ' x é False.
x = Not 23 > 67 ' x é True.
No exemplo acima, o operador Not executa uma operação de negação, e simplesmente muda a
forma de avaliação proposta. Assim X não avalia 23 > 2, portanto é falso, em seguida X não avalia
23 > 67 então é verdadeiro.
Dim x As Boolean
x = 23 > 12 And 12 > 4 ' x = True
x = 12 > 23 And 12 > 4 ' x = False
Acima, o operador And executa uma operação de junção entre duas expressões, e retorna
verdadeiro se todas as expressões forem verdadeiras. Se todas as expressões forem falsas, o resultado
é falso. Se uma delas for verdadeira e outra false, ainda assim o resultado é falso.
Dim x As Boolean
x = 23 > 12 Or 4 > 12` ' x = True
x = 23 > 45 Or 4 > 12 ' x = False
O operador Or acima, executa uma operação de disjunção entre duas expressões, Se ambas as
expressões forem verdadeiras o resultado é True. Se ambas as expressões forem false, o resultado é
false. Mas se uma das expressões forem verdadeiras, então o resultado é True.
Dim x As Boolean
56
x = 23 > 45 Xor 12 > 4 ' x = True
x = 23 > 12 Xor 12 > 4 ' x = False
x = 12 > 23 Xor 4 > 12 ' x = False
No exemplo acima, o operador Xor executa uma operação de exclusão entre duas expressões. Se
ambas as expressões forem verdadeiras, o resultado é False. Se ambas as expressões são falsas, o
resultado ainda é False. Mas se uma das expressões for verdadeira e outra falsa, o resultado final é
verdadeiro.
Dim x As Boolean
x = 23 > 12 And msgbox(“Olá”) ' exibe a mensagem Olá
x = 12 > 23 And msgbox (“Olá”) ' Não exibe a mensagem Olá
No exemplo acima, o operador AndAlso executa uma operação de junção, semelhante ao operador
And, a única diferença é que se a primeira expressão for falsa o operador AndAlso não avalia a
segunda expressão, e o resultado será false. Ao passo que o operador And, avalia as duas expressões
obrigatoriamente e também retorna false.
Dim x As Boolean
x = 23 > 12 OrElse msgbox (“Olá”) ' não exibe a mensagem Olá
x = 23 > 45 OrElse Msgbox ( “Olá”) Exibe a mensagem Olá
Acima, o operador OrElse executa uma operação de disjunção entre duas expressões, semelhante ao
operador Or, a única diferença é que se a primeira expressão for verdadeira o operador Or não avalia
a segunda expressão e o resultado será false. Ao passo que o operador Or, avalia as duas expressões
obrigatoriamente e também retorna false.
Operadores Bitwise
As operações Bitwise avaliam valores em formato binário, e comparam os bits em suas posições
correspondentes, em seguida retornam o resultado da comparação. Exemplo :
Dim x As Integer
x = 3 And 5 ' x = 1
No exemplo acima, não há comparação entre expressões, mas entre números inteiros com o operador
And. Portanto o compilador transforma os números em formato binário e executa a comparação em
bitwise.
57
Dim x As Integer
x = 3 or 5 ' x = 7
011 3 em decimal
101 5 em decimal
111 O resultado em formato binário.
Convertendo para o formato decimal, 111 é o formato binário do número 7, então x = 7
Dim x As Integer
x = 3 Xor 5 ' x = 6
011 3 em decimal
101 5 em decimal
110 O resultado em formato binário.
Convertendo para o formato decimal, 110 é o formato binário do número 6, então x = 6
Dim x As Integer
x = Not 5 ' x = -6
Resumindo : As operações em Bitwise só podem ser efetuadas com tipos de dados Integer. Os outros
tipos de dados devem ser convertidos obrigatoriamente para Integer.
5. Operadores de atribuição
Operador =
Usado para atribuir um valor a uma variável ou propriedade. Exemplo :
myInt = 42
Operador ^=
Usado para elevar o valor da variável à potência definida a direita do operador, e atribui o resultado a
variável. Exemplo :
Observe que o operador substitui a expressão var1 = 10 ^ 3. Essa é a forma mais eficiente para
efetuar cálculos.
58
Operador *=
Usado para multiplicar o valor da variável pelo valor definido a direita do operador, e atribui o
resultado a variável. Exemplo :
Observe que o operador substitui a expressão var1 = 10 * 3. Essa é a forma mais eficiente para
efetuar cálculos.
Operador /=
Divide o valor da variável pelo valor definido a direita do operador, e atribui o resultado a variável.
Exemplo :
O operador substitui a expressão var1 = 12 / 3. É a forma mais eficiente para efetuar esse cálculo.
Operador \=
Usado para dividir os inteiros da variável pelo valor definido a direita do operador, e atribui o
resultado a variável. Exemplo :
O operador substitui a expressão var1 = 10 \ 3. É a forma mais eficiente para efetuar esse cálculo.
Operador +=
Adiciona o valor definido a direita do operador a variável. Além disso concatena a string definida a
direita do operador a variável string. Todos os resultados obtidos são atribuídos a variável. Exemplo :
O operador substitui as expressões var1 = 10 + 3, e var1 = “10” & “3”. São as formas mais eficientes
para executar essas operações. As conversões devem obedecer o comportamento de acordo com a
opção Option Strict.
Operador -=
Usado para subtrair o valor definido a direita do operador da variável, e atribui o resultado a variável.
Exemplo :
59
Dim var2 As Integer = 3
var1 -= var2 ' O valor de var1 é agora 7.
O operador acima substitui a expressão var1 = 10 – 3. É a forma mais eficiente para executar essa
operação.
Operador &=
Usado para concatenar a string definida a direita do operador com a string da variável, e atribui o
resultado a variável. Exemplo :
O operador substitui a expressão var1 = “Hello ” & “World”. É a forma mais eficiente para
concatenar essas strings.
Todos os operadores descritos acima aceitam expressões, funções, constantes após os operadores.
Como por exemplo :
6. Operadores Gerais
Os operadores gerais são todos os operadores que não se enquadram nas divisões acima. São dois os
operadores gerais.
Operador AddressOf
Usado para criar uma referência que aponta para um procedimento ou função definidos após esse
operador, isto significa que o operador vai sempre executar o nome da função a direita do operador.
Esse tipo de operador é usado com o recurso Delegate do VB .Net, que será estudado mais tarde,
para manter um ponteiro para uma função ou procedimento mesmo que esta já tenha sido descartada
na memória.
Em versões anteriores do VB, esse operador era usado para passar o endereço de memória de um
procedimento para uma Função API do Windows.
No exemplo acima, foi criado um procedimento ButtonClickHandler que exibe a mensagem “Outro
evento para o botão”. Em seguida, no evento New de uma janela do VB, foi criado um método para
60
mudar o curso do evento Clique de um botão para o novo procedimento ButtonClickHandler
utilizando o operador AddressOf.
Observe que o não existe código algum no evento Click do botão de comando.
Operador GetType
Usado para informar o tipo de objeto que uma variável pertence, além disso pode retornar
propriedades, métodos e eventos do respectivo tipo. Exemplo :
O resultado do teste é :
Int32
Int32
String
Double()
O exemplo acima, cria uma variável como uma matriz de tipos Type( ) e inicializa seus valores com
o operador GetType. Em seguida, escreve os resultados na janela Output do Visual Studio.
7. Precedência de operadores
Operadores de Comparação
1. Igualdade (=)
2. Diferenciação (<>)
3. Menor que, Maior que (<,>)
4. Maior ou igual à (>=)
5. Menor ou igual à (<=)
6. Like
7. Is
8. TypeOf...Is
61
É possível alterar a ordem de precedência dentro de uma expressão, utilizando parênteses entre os
membros da expressão. Exemplo :
Um procedimento pode ser invocado em qualquer lugar do código. Assim, quando o procedimento
termina sua execução, o controle do processo retorna ao código que o chamou. O código que invoca
o procedimento é conhecido como código de Chamada (calling code).
• Procedimentos Sub que executam uma ação mas não retorna valor algum.
• Procedimentos Manipulação de Eventos que são invocados em resposta a uma ação
exercida pelo usuário ou por uma ocorrência do programa.
• Procedimentos em Funções que executam ações e retornam valores.
• Procedimentos Property (propriedades) que tanto podem retornar valores ou receber valores
para um objeto ou módulo.
Todos os procedimentos Sub são iniciados com o comando Sub e finalizados com End Sub. Além
disso podem ser precedidos por qualquer comando de declaração Public, Private, Protected, Friend e
Protected Friend. Observe que qualquer procedimento Sub é declarado como Public por Default,
quando não há comandos de declaração explícitos. Exemplo:
No exemplo acima o procedimento Sub ChamarOperador exibe uma mensagem do horário atual da
chamada, e apesar de exibir a mensagem “Iniciando a chamada às XX:XX:XX” não retorna nenhum
valor.
End Sub
Todos os procedimentos em Função são iniciados com o comando Function e finalizados com End
Function. Além disso podem ser precedidos por qualquer comando de declaração Public, Private,
Protected, Friend e Protected Friend e devem obrigatoriamente retornar um tipo de dados ou objeto.
Todas as funções são Public por default, quando não há comandos de declaração explícitos.
Além disso o código da função é executada automaticamente até encontrar os comandos Exit
Function, Return ou End Function. Exemplo:
• Exit Function – Finaliza uma função sem antes ter atingido o final das instruções.
• Return – Palavra chave que retorna um valor para o código de chamada (Calling Code).
• End Function – Comando para finalizar a função normalmente.
Dim a As Integer = 2
Dim b As Integer = 2
End Function
Número = Somar2e2 ( )
Msgbox (Número)
End Sub
No exemplo acima, a função Somar2e2 demonstra uma função, muito simples e totalmente sem
propósito, como retornar valores integer para o código de chamada.
63
Conforme o fragmento acima, a regra principal para utilizar uma função é igualar os tipos de dados,
se a variável do caso acima for Integer e a função TotalArquivosTexto retornar um valor numérico
integer, o objetivo foi alcançado.
No código acima, a função Tudoum( ) retorna uma matriz de inteiros e exibe uma mensagem “Ainda
passa por aqui”. O evento Click de um botão chama a função e após o comando m = Tudoum( ) a
função ainda continua a execução exibindo a mensagem.
Ao passo que substituindo o comando Tudoum = x por Return x, a mensagem não seria exibida.
Porém, observe que a forma do exemplo acima, permite que o desenvolvedor execute testes
adicionais para comprovar o cálculo ou atribua novos valores ao procedimento, mas Return não
permite.
• Funções Intrínsecas – São as funções incluídas no VB, assim com : Sqr, Cos, Chr, e estão
incluídas no espaço nomeado Microsoft.VisualBasic.
• Funções Extrínsecas – São as funções personalizadas criadas pelo desenvolvedor.
Observe que se a função retornar valores em matrizes, não é permitido acessar os elementos
individuais da matriz dentro da função porque o compilador pode interpretar uma nova chamada a
função. Exemplo :
No exemplo acima, não é possível acessar os elementos da função TudoUm ( ) , ao invés disso crie
variáveis matriz para acessar cada elemento individualmente. Exemplo :
65
Se dois ou mais módulos possuírem funções ou procedimentos com o mesmo nome, é necessário
excepcionalmente nestes casos, utilizar a estrutura hierárquica (nomear o módulo) onde estão
localizadas. Exemplo :
Module2.TocarArquivosSom
Class MinhaClasse
' Variável local para armazenar o valor de uma propriedade.
Private ValorDaPropriedade As String
' Cria e define a propriedade.
Public Property Propriedade1() As String
Get
' Get é chamado quando a propriedade retorna
' Isto é quando algum código de chamada tenta ler o valor dessa propriedade
Return ValorDaPropriedade
End Get
Set (ByVal Valor As String)
' Set é chamado quando o valor da propriedade é modificada
' O valor a ser atribuído é passado no argumento Valor
ValorDaPropriedade = Valor
End Set
End Property
End Class
End Sub
O exemplo acima, resume todas as tarefas necessárias para criar propriedades em uma classe
chamada MinhaClasse. Observe que a regra geral é sempre criar variáveis locais para guardar os
valores das propriedades e utilizar as palavras chaves Get e Set para tornar as propriedades Leitura-
Gravação. Em seguida o evento clique de um botão de comando criar uma instância (uma cópia) da
classe MinhaClasse e manipula a propriedade do objeto criado. Os procedimentos Procedures serão
estudados no capítulo “VB e a programação orientada a objeto”.
1. Argumentos em procedimentos
Algumas funções e procedimentos podem necessitar de informações adicionais para executarem suas
tarefas, essas informações são enviadas pelo código de chamada e podem ser variáveis; constantes;
expressões e objetos. Cada valor passado para o procedimento é chamado de argumento. Exemplo :
66
No exemplo acima, a função Somar possui dois argumentos Número1 e Número2 que são utilizados
no cálculo da soma dos valores. Cada argumento deve ser explicitamente declarado com um tipo de
dados, além disso podem haver vários argumentos em conjunto. A forma correta para a função acima
seria :
Private Function Somar (ByVal Número1 as integer, ByVal Número2 as Integer) as Integer
End Function
• Argumentos passados por valor (ByVal) – Os argumentos ByVal são apenas cópias do
valor dessas variáveis, e portanto qualquer alteração dessas variáveis decorrentes do código
da função ou procedimento, não afetará o valor original da variável. O tipo ByVal é o Default
nas funções em Visual Basic.
• Argumentos passados por Referência (ByRef) – Os argumento por referência, o valor
original do argumento é utilizado e qualquer mudança neste valor decorrente do código da
função ou procedimento afetará o valor original da variável.
Os argumento ByVal, são ponteiros de dados, e não valores de dados , isto implica dizer que não há
como mudar um valor se o VB não tem acesso ao conteúdo da memória, somente o endereço. Ao
passo que, argumento por referência, o VB tem acesso ao conteúdo da memória no endereço
específico, assim qualquer alteração do valor dessa variável, afetará o conteúdo da memória e
conseqüentemente a variável original será alterada permanentemente.
O compilador do VB não trata os tipos de dados dos parâmetros da mesma forma entre ByVal e
ByRef. Veja o quadro abaixo :
Assim os argumentos por Valor são considerados elementos não variáveis, pois não podem ser
alterados pela função ou procedimento, portanto o compilador trata os tipos de variáveis como
constantes, literais, enumeradores e expressões.
67
Observe que ByVal não permite alterar os próprios valores, entretanto é possível alterar os membros
do objeto que ele aponta. Por exemplo, é possível alterar, mas não atribuir uma nova matriz para um
argumento matriz. Exemplo:
Quando um argumento variável do tipo objeto é passado por Referência, pode-se atribuir um novo
objeto a esse argumento e a alteração também se refletirá no código chamador. Assim no exemplo
acima, se Replace utilizasse argumentos por Referência, e K ( ) fosse atribuída a N ( ), os valores
teriam sido os seguintes:
' N() agora seria 101, 201, and 301. Porque N foi passado por ByRef
' Replace também modificaria N e também atribuiria uma nova matriz para ele.
O compilador VB pode forçar o uso de argumentos ByRef em ByVal através do código Chamador,
incluindo os argumentos entre parênteses. Exemplo :
68
Sub AlgumaCoisa(ByRef MinhaVariável As String)
' Código que faz alguma coisa.
End Sub
' ...
Call AlgumaCoisa((Str)) ' Envia Str como ByVal mesmo que o procedimento seja ByRef.
' O parênteses Str protege a variável contra alterações.
O exemplo acima utiliza um procedimento AlgumaCoisa que possui argumentos por Referência,
entretanto o código Chamador envia o argumento Str como Valor (ByVal).
Sempre que o VB encontrar funções ou procedimentos sem as palavras chaves ByVal ou ByRef, o
mecanismo padrão de passagem de argumentos é por Valor ByVal. Entretanto a Microsoft
recomenda sempre utilizar as palavras chaves para declarar explicitamente como os argumentos
devem ser passados pelo código chamador.
É possível passar argumentos pela posição, isto é pela ordem em que eles foram declarados na
função ou procedimento. Exemplo :
Sub StudentInfo(ByVal Name As String, Optional ByVal Age As Short = 0, Optional ByVal Birth
As Date = #1/1/2000#)
Debug.WriteLine(Name, Age, Birth)
End Sub
No exemplo acima foi criado um procedimento chamado StudentInfo com 3 argumentos. Para o
código chamador, basta preencher os argumentos e separá-los com vírgula para cada posição.
Observe porém que em um dos códigos foi omitido o parâmetro Age pois foi definido no
procedimento original como Opcional (Optional). O parâmetro omitido deve ser seguido por vírgula
normalmente.
Para passar argumentos por nome, basta nomear os argumentos seguidos por dois pontos e igual ( :=
) e atribuir os valores. Exemplo :
Observe que não é preciso obedecer as posições dos argumentos quando se passar argumentos por
nome. Além disso pode-se combinar argumentos por nome e por posição como no exemplo abaixo :
Note ainda que não é preciso incluir vírgulas no argumento omitido, pois os argumentos por nome já
indicam ao compilador que um dos argumentos opcionais devem ser omitidos. Outra observação
69
importante é que, uma vez um argumento fornecido por nome, todos os argumentos posteriores
devem ser fornecidos por nome.
• Para fornecer parâmetros por posição inclua vírgulas entre os parâmetros obedecendo sempre
a ordem dos parâmetros.
• Para fornecer parâmetros por Nome inclua vírgulas entre os parâmetros, nomeie os
parâmetros e digite : = (dois pontos e vírgula). Não é preciso obedecer a ordem dos
parâmetros.
• Só é possível omitir os parâmetros quando o procedimento original definir o parâmetro como
Optional. Além disso, os parâmetros omitidos devem ser seguidos de vírgula, exceto quando
fornecer parâmetros por Nome.
• É possível fornecer tanto parâmetros por Nome e por posição no mesmo procedimento,
entretanto uma vez fornecido um parâmetro por Nome, todos os outros parâmetros devem ser
informados por nome.
• Não é possível fornecer parâmetros Matriz por Nome.
Um procedimento pode definir um parâmetro como opcional (Optional), desta forma o código
chamador pode omití-lo no momento de invocar o procedimento. Para isso basta utilizar a palavra
chave Optional. Exemplo :
Para chamar um procedimento opcional, basta omitir o valor e incluir vírgulas na posição do
argumento. Exemplo :
No exemplo acima o procedimento Notify utilizar um argumento Optional Office com um valor
padrão QJZ, para inspecionar se o argumento foi explicitamente informado pelo código chamador,
basta comparar com o valor padrão QJZ, se o valor for diferente então significa que o código
chamador forneceu outro valor.
70
Quando um procedimento é construído para receber 3 argumentos, o VB exige no máximo a
passagem de 3 argumentos. No entanto, pode-se criar procedimentos que aceitam receber um número
arbitrário de argumentos, para isso utiliza-se a Palavra-chave ParamArray. Exemplo :
No exemplo acima foi criado um procedimento NotasEstudantes com um parâmetro Nome e outro
Parâmetro em matriz Notas que exibem uma mensagem na tela para nome de aluno. Em seguida um
código de chamada invoca o argumento fornecendo um nome de estudante e várias notas.
• Um procedimento só pode ter uma matriz de parâmetros, e deve ser sempre o último
argumento de um conjunto de argumentos.
• Toda matriz de parâmetros é sempre passado por valor. Use sempre a palavra chave ByVal.
• O código dentro do procedimento deve trabalhar a matriz de parâmetros como uma matriz
unidimensional.
• Todos as matrizes de parâmetros são automaticamente opcionais por default.
• Todos os argumentos antes da matriz de argumentos não podem ser opcionais (Optional). A
matriz de parâmetros deve ser o único argumento opcional.
• O código de chamada pode omitir um argumento do tipo matriz de argumentos, além disso é
possível enviar a palavra chave Nothing como argumento que tem o mesmo efeito.
• Pode-se enviar no código chamador uma lista indefinida de elementos para a matriz.
• Pode-se enviar no código chamador uma matriz diretamente como argumento desde que seja
do mesmo tipo.
A palavra-chave ParamArray deve utilizar mais recursos do sistema em comparação a uma função
construída com número definido de argumentos, pois tratando-se de coleções ou matrizes, o VB tem
um trabalho maior em manipular essas estruturas.
5. Procedimentos recursivos
Um procedimento é chamado de recursivo quando ele chama a si próprio. Recursão é uma técnica
característica de linguagens avançadas que permite que um código dentro de um procedimento
chame o próprio procedimento. Exemplo :
O exemplo acima cria uma função que calcula o fatorial de um número, a simplicidade do código
está na linha Return Factorial (N – 1) * N que chama o próprio procedimento.
Para utilizar recursão é preciso colocar o nome do procedimento em seguida incluir parênteses,
mesmo que o procedimento não utilize argumentos, caso contrário o compilador entende que a
função termina neste ponto e retorna um valor qualquer.
É preciso certificar-se que os procedimentos recursivos não irão causar erro de falta de espaço em
memória, por utilizar indefinidamente a recursão. Além disso é possível substituir normalmente
loops por recursão.
No exemplo acima, há um único procedimento Z implementado com versões contendo uma lista de
argumentos diferentes. Para criar um overloading é necessário seguir as regras abaixo :
Exemplo :
Utilizando a palavra chave Overloads e o nome de um procedimento, define-se várias versões desse
procedimento.
72
Exemplo :
Sub P (ByVal D As Date, ByVal ParamArray C() As Char)
Collection (Coleções) é uma maneira de agrupar tipos de objetos enquanto que matrizes é mais
eficiente em agrupar variáveis. Pode-se usar coleções quando trabalharmos com um pequeno
conjunto de itens ou membros que possuam as mesmas características, podendo variar de janelas
abertas até endereços URL de internet.
As coleções são trilhas de objetos comuns e não podem ser redimensionados quando se adiciona
novos membros a coleção. Há coleções de formulário, coleções de controles, coleções de
impressoras, e além disso o VB oferece coleções genéricas, que permite criar nossas próprias
coleções personalizadas.
Uma coleção armazena cada item como um tipo de dados Objeto, assim tudo aquilo que você utiliza
para ser armazenado em uma variável objeto pode ser adicionado a coleção, exceto os tipos de dados
compostos que não são suportados.
Os tipos de dados compostos devem ser utilizados somente em matrizes, entretanto um Collection é
muito mais veloz do que matrizes, já que utiliza apenas 16 bytes em memória não importanto o que
se armazena nele.
Essas propriedades e métodos da interface de um objeto Collection, permitem utilizar todos os seus
serviços.
• Uma chave (Key) é um valor em String, que é um nome de identificação para o elemento.
• Um índice (Index) é um número Long que vai de 1 (hum) até o número de elementos do
Collection.
A Microsoft recomenda utilizar uma estrutura For each…Next, para interagir com uma collection,
(ver estruturas de controle e decisão).
73
Para criar uma coleção utilize o comando Collection. Exemplo :
A palavra chave New, instrui o VB a inicializar uma coleção imediatamente e depois criar a coleção
após a variável ser referenciada em código.
Note que foi adicionado um objeto novoItem, poderia ser qualquer formulário, ou outro objeto
qualquer que contenha uma propriedade própria ID que seria uma identificação em string do objeto.
Essa propriedade funciona apenas como uma identificação imaginária, apenas para demonstrar que é
neste ponto onde será criada uma identificação para o objeto na coleção. É importante observar que
as coleções podem ser iniciadas a partir de índice zero (0) ou índice hum (1).
No outro exemplo acima, utilizou-se um argmento nomeado after, que é usado para posicionar esse
item na posição número 3. Poderia, entretanto, usar o argumento nomeado before, para posicionar o
item antes do item número 2, sendo assim ele seria o segundo item da lista, e todo o restante seria
reposicionado adequadamente.
Caso before : = 1, o item seria o primeiro da lista, e todos os subsequentes seriam adicionado com 1
em suas posições. A sintaxe dos argumentos nomeados é sempre seguido de dois pontos ( : ) e igual
(=) :
Before : = valor
After : = valor
Note ainda que, a instrução novoItem.ID precisa ser do tipo String, caso contrário deverá ser
convertido para o tipo de dados String com a função CStr.
nomedaVariável.Remove 3
OU
nomedaVariável.Remove "W017493"
No exemplo acima, o argumento index (índice) pode ser tanto a posição do item na coleção quanto a
sua identificação (Key).
Como se pode observar no exemplo acima, é necessário declarar uma variável onde será atribuido o
valor retornado da coleção . Utilizou-se a palavra chave Set para atribuirmos o valor de um objeto a
variável.
74
A regra principal a ser seguida é :
Collection também se beneficia de um método Default em sua interface, pois Collection é realmente
um objeto. O método Default do objeto Collection é Item, assim para retornar o valor de um item,
usa-se :
É necessário ter em mente que quando apagamos ou adicionamos novos membros a coleção, o VB
automaticamente ajusta os índices de cada membro, alterando-o. A Microsoft recomenda utilizar o
Key (identificação) para retornar valores de uma collection, para evitar confusão entre índices
alterados.
Como Collection é um conjunto de objetos relacionados e todos possuem sua interface, é possível
manipular suas propriedades e métodos através do método Item do objeto Collection. No exemplo
abaixo, utilizou-se a uma propriedade chamada Prioridade do item W017493 da coleção
colWorkOrders :
colWorkOrders.Item("W017493").Prioridade = 3
colWorkOrders("W017493").Prioridade = 3
Observa-se que os dois fragmentos de código utilizam o método Item da coleção para alterar a
propriedade Prioridade, sem que fosse declarado uma variável com Set, conforme foi visto na sintaxe
no início do tópico. Isso foi possível, pois apenas uma propriedade do objeto em questão foi alterado,
não havendo a obrigação de criar uma variável somente para essa tarefa.
Entretanto, é mais viável por questões de velocidade a utilização de uma variável altamente tipificada
para receber a cópia de uma coleção, e em seguida manipularmos as propriedades e métodos do
membro da coleção :
A variável Meu foi declarada implicitamente como um objeto colWorkOrders, e o VB interpreta uma
variável de objeto mais rapidamente que Collection, pois este último armazena os seus itens como
Object (Veja explicação acima) tornando-os muito lentos para acesso e manipulação.
75
As coleções pré-construídas do Vb não permitem que o desenvolvedor adicione ou remova seus itens
através do código, como por exemplo a coleção CheckedListBox.CheckedItems não possui os
métodos Add ou Remove.
As estruturas de controle atuam sobre o fluxo do programa e são organizadas através de estruturas de
decisão e estruturas de Loop. São comuns a todas as linguagens de programação.
As estruturas de decisão são instruções de condições de teste e conforme o resultado executa a ação.
If...Then …End if
If...Then….Elseif ….Else
Select Case .... End Select
Try...Catch...Finally
Exemplo :
A estrutura Select Case avalia uma expressão somente uma vez no início da estrutura, enquanto que
a estrutura If ... Then... Else avalia a mesma expressão para cada ElseIf. A estrutura Select Case é
mais eficiente do que If ... ElseIf se , e somente se o comando If e ElseIf avaliar a mesma expressão.
Os comandos Try... Catch... Finally são usados para interceptar exceções (erros) em um bloco de
código particular. Quando um código potencialmente pode gerar erros de compilação, basta colocar o
76
código na estrutura Try... Catch... Finally que o compilador intercepta o erro e permite que o
desenvolvedor crie um procedimento capaz de resolver o problema.
Qualquer código dentro dessa estrutura inicia a execução em Try, se não houver nenhuma incidência
de exceções (erros ) o VB vai diretamente para o comando Finally até o final do procedimento. Ao
passo que quando há exceções o VB vai diretamente para o comando Catch (se houver) e então
prossegue até o comando Finally ( se houver ) até o final, isto é End Try. Portanto o bloco de
código em Finally será sempre o último a ser executado.
O procedimento escrito dentro do bloco Catch deverá ser criado para interceptar e corrigir o erro
gerado por um código em particular, além disso o bloco Catch permite especificar o tipo de exceção
(erro) que a estrutura deverá interceptar e corrigir.
Se o tipo de erro em Catch não for especificado, esse bloco de código irá interceptar todo e qualquer
tipo de erro gerado pelo código em questão, neste caso quando o código em Catch não foi projetado
para interceptar e corrigir esse tipo de erro, o Visual Studio exibe uma mensagem de erro
normalmente.
O exemplo acima demonstra o uso da estrutura Try, Catch, Finally que intercepta somente o erro de
divisão por zero. O código que gerou o erro está em Try x /= y pois y = 0 , em seguida o comando
Catch intercepta o erro quando y = 0, observe que ex é uma variável qualquer que recebe o tipo de
erro retornado pelas classe de exceção do .Net Framework.
O exemplo acima é um fragmento de código que após receber uma data e horário em DataQualquer
testa a adição de 100 anos para o valor original. Se o valor resultante ultrapassar o limite de data do
77
VB ( maior de Dezembro de 9999) o bloco Em System.ArgumentOutOfRangeException entra em
ação e exibe a mensagem “O Resultado é maior que 32 de Dezembro de 9999”. Da mesma forma se
ocorrer um erro não previsto o código em Catch exibe a mensagem “Ocorreu uma exceção
desconhecida”.
Observe ainda que é possível criar quantos comandos Catch desejar para interceptar uma quantidade
grande de exceções.
While...End While
Do...Loop (ramificações abaixo)
Do Until …. Loop
Do…. Loop Until
For...Next
For Each...Next
O comando While ... End While é usado para executar um bloco de código em um número
indefinido de vezes dependendo do valor de uma condição testada. Exemplo :
O comando While sempre executa o teste antes de iniciar o loop. Para encerrar um loop infinito basta
pressionar a tecla ESC ou CTRL + BREAK em RunTime. (código em Execução).
A estrutura Do…Loop tem duas formas de construção, com uma única diferença, a primeira forma
Do Until pode não executar um looping, enquanto que a última forma Do..., executa
obrigatoriamente pelo menos um looping.
Do Until condição Do
comandos comandos
Loop Loop Until condição
Exemplos :
For i = 0 To Screen.FontCount
Print Screen.Fonts(i)
Next
For i =1 to 14 Step 2
Next I
No antepenúltimo exemplo, a estrutura For… Next usa um objeto global Screen.FontCount como
contador (propriedade FontCount), enquanto que no penúltimo exemplo a estrutra For Each... In..., é
ligeiramente diferente, pois é usado para coleções de objetos, e tem a seguinte estrutura :
Elemento pode ser um controle qualquer que faz parte de uma coleção e é muito útil quando o
desenvolvedor não sabe o número exato de elementos de uma coleção ou matriz. Entretanto é
necessário seguir algumas regras no uso dessa estrutura específica :
• Dentro de coleções, o elemento não pode ser uma variável objeto, ou uma variável de objeto
genérica ou um objeto listado no Object Browser.
• Para as matrizes, o elemento não pode ser uma variável Objeto.
• Não se pode utilizar essa estrutura com uma matriz do tipo composta definidos pelo usuário
pois um Objeto não pode conter um tipo definido pelo usuário.
O comando Exit é usado para finalizar um loop, um comando de decisão, um procedimento ou uma
função bruscamente. A única preocupação é combinar o comando Exit com a estrutura utilizada.
79
As estruturas acima listadas podem trabalhar dentro de outras, essa característica especial é chamada
de estruturas aninhadas (A Microsoft utiliza o termo Nested), formando um conjunto de loops e
decisões coexistentes, obedecendo níveis segundo a construção do bloco de código. A indentação de
código (tabulação das linhas) é necessário para tornar o código mais legível e de fácil identificação
dos níveis.
O fragmento de código abaixo , apresenta uma estrutura aninhada , com indentação de linhas, cujo
primeiro nível é uma estrutura de loop, o segundo nível é uma estrutura de decisão e o terceiro e
último nível (mais profundo) é também uma estrutura de decisão :
For i = 0 To frmVCR.Controls.Count - 1
If TypeOf frmVCR.Controls(i) Is Shape Then
If frmVCR.Controls(i).Name = MyControl Then
frmVCR.Controls(i).Visible = True
Else
frmVCR.Controls(i).Visible = False
End If
End If
Next
No VB, ainda há a estrutura With…End With que permite executar referências repetidas a um
único objeto, em outras palavras ao invés de repetir o mesmo nome do objeto ao usar sua interface
basta apenas colocar os códigos do objeto dentro da estrutura With....End With precedidos com
ponto ( .) .
MeuLabel.Height = 2000
MeuLabel.Width = 2000
MeuLabel.Text = “Este é o meu Label”
With MeuLabel
.Height = 2000
.Width = 2000
.Text = "Este é o meu Label"
End With
Observe no código acima que o controle Label “MeuLabel” foi invocado três vezes para atribuir
valores para as propriedades Height, Width e Text respectivamente, enquanto que no código seguinte
o mesmo controle foi invocado apenas uma vez na estrutura With...End With.
Além de economizar tempo de digitação a Microsoft recomenda utilizar sempre esta estrutura para
criar um código de alto desempenho e eficiência.
Exit Select
Exit Try
Exit Do
Exit While
Exit For
Exit Sub
Exit Function
Exit Property
80
Exemplo :
Do Until y = -1
If x < 0 Then Exit Do
x = Sqrt(x)
If y > 0 Then Exit Do
y=y+3
If z = 0 Then Exit Do
z=x/z
Loop
O código acima demonstra um loop com uma estrutura aninhada* que é encerrada quando os
valores de x, y e z são zero. Observe que Exit é completamente diferente de End, pois Exit transfere
o controle do sistema diretamente ao procedimento chamador (quando houver), ao passo que End
finaliza completamente a execução do programa.
*Estrutura aninhada – É uma técnica que consiste em criar comandos de decisão ou de desvios
dentro de outros comandos de decisão ou desvios, utilizando indentação de linhas.
Sub DemonstraçãoDoExit()
Dim I, MyNum As Integer
Do ' loop infinito
For I = 1 To 1000 ' Loop de 1000 vezes
MyNum = Int(Rnd * 1000) ' Cria um número aleatório.
Select Case MyNum ' Avalia o número.
Case 7: Exit For ' se 7, exit For...Next.
Case 29: Exit Do ' se 29, exit Do...Loop.
Case 54: Exit Sub ' se 54, exit Sub procedure.
End Select
Next I
Loop
End Sub
Além das estruturas acima, há comandos e palavras chaves que também executam desvios de fluxo
do programa:
Comando GoTo : Desvia o fluxo do programa para uma linha nomeada dentro do procedimento.
Exemplo :
GoTo LInhaDois
MsgBox("Nunca vai passar aqui")
LinhaDois:
MsgBox("entou na linha dois e fecha o procedimento")
End Sub
End Class
81
No exemplo acima o evento clique de um botão utiliza o comando GoTo para desviar o fluxo do
procedimento para uma linha nomeada “LinhaDois” e exibir a mensagem “entrou na linha dois e
fecha o procedimento”. Observe que a sintaxe do comando é sempre GoTo NomeDaLinha, em
seguida é preciso criar uma linha nomeada com dois pontos ( : ), não é possível utilizar indentação
em linhas nomeadas.
O comando GoTo cria códigos difíceis de ler e de serem revisados, portanto não utilize esse tipo de
comando no aplicativo.
Comando On Error : Permite desviar o fluxo do programa para uma linha nomeada que trata erros
de execução do código. O comando On Error é especialmente útil para interceptar e tratar erros de
execução, quando um procedimento aciona um erro o programa é desviado automaticamente para o
procedimento que trata o tipo de erro específico.
O exemplo acima “IniciarMatriz” disponibiliza uma manipulação de erro através do comando Goto
ErrorHandler, note que ErrorHandler é o nome de uma linha nomeada no código. Dentro da linha
nomeada deve ser escrito o código que trata do erro específico. Observe que sempre ao utilizar uma
linha nomeada é preciso incluir o comando Exit Sub ou Exit Function antes da linha nomeada, para
evitar que o fluxo do programa processe os comandos da linha nomeada.
Sub Form_Load()
82
Dim Password, Pword As String
PassWord = "Swordfish"
Pword = InputBox("Digite a Senha")
If Pword <> PassWord Then
MsgBox ("Desculpe, senha incorreta")
End
End If
End Sub
No exemplo acima o evento Load de uma janela exibe uma mensagem para digitar Senha, se o
usuário digitar qualquer coisa diferente de “Swordfish” não só o procedimento é encerrado mas todo
o aplicativo é finalizado instantaneamente.
Comando Stop : Suspende a execução do aplicativo, o mesmo efeito do botão pause do ambiente
Visual Studio .NET.
Dim I As Integer
For I = 1 To 10 .
Debug.WriteLine (I) ' Imprime I na janela Output
Stop ' Pára a execuação do loop até que o usuário escolha continuar.
Next I
Função Choose : Seleciona e retorna o valor de uma lista de argumentos. A sintaxe da função é :
Public Function Choose (ByVal Index As Double, ByVal ParamArray Choice() As Object) As
Object
End Sub
No código acima a função Escolha retorna um tipo de string para o número informado Ind. No
procedimento de evento Clique de um botão foi invocado a função Escolha com o índice 2, neste
caso corresponde ao string “Ajato”.
Função Switch : Avalia uma lista de expressões e retorna um valor associado com a primeira
expressão encontrada na lista. A sintaxe da função é :
83
Dim A as integer = 2
Dim B as integer = 2
Dim C as integer = 2
Msgbox (Microsoft.VisualBasic.Switch(A<2,“Letra A < 2”, B=2, “Letra B = 2”, C<3, “Letra C<3”))
Valor Impresso : Letra B = 2
A lista de argumentos da função Switch consiste de pares de expressões e valores. As expressões são
avaliadas à medida que aparecem na lista da esquerda para a direita e é retornado o valor associado à
primeira expressão para avaliar True. No exemplo acima as expressões são comparações entre A,
B,C e os valores retornados são os string do tipo “Letra A < 2”.
Método Call : Transfere o controle do aplicativo para um procedimento, Função ou DLL definido
após o método Call.
Call ExibirJanela( )
Call Shell("C:\Windows\calc.exe", AppWinStyle.NormalFocus)
Comandos Property, Function, Sub : Comandos usados para declarar blocos de código como
propriedades, funções e procedimentos Sub respectivamente. O controle do fluxo do programa é
desviado para o código entre a estrutura Property... End Property, Function .... End Function,
Sub ... End Sub.
Tudo o que é feito em VB está associado a objetos, ou melhor ainda à programação orientada a
objeto ou object orientation program (oop).
Toda a programação orientada a objeto está ligada a criação de classes e objetos. Uma classe, como
já foi estudado anteriormente, é o protótipo de um objeto em fase de implementação (construção).
Um objeto é uma classe já implementada e em uso por algum outro bloco de código ou
desenvolvedor.
Todo código VB útil pode-se tornar uma classe, podendo ser reutilizado por outros códigos ou por
outros desenvolvedores. Ao invés de copiar e colar o código pronto, basta fazer uma referência a
classe e utilizá-a no aplicativo em construção.
Toda classe possui campos (Fields), propriedades, métodos e eventos. Os campos ou propriedades
são valores ou informações sobre um objeto. Os campos são variáveis puras dentro de classes que
retornam informações e recebem valores diretamente. As propriedades são similares as variáveis,
entretanto são implementadas com maior controle sobre o conteúdo que elas recebem. Os Métodos
são procedimentos que o objeto pode executar. Os Eventos são notificações que o objeto dispara em
resposta a uma ação desenvolvida pelo usuário ou pelo sistema.
84
3. Polimorfismo (Polymorphism) - É a habilidade que uma classe deve possuir para permitir
que um mesmo nome de propriedade não importa que tipo de dados seja, execute diferentes
tarefas. Portanto não é preciso criar vários métodos ou propriedades diferentes para criar
tarefas diferentes, basta utilizar a habilidade polimórfica para usar um único nome de método
ou propriedade com implementações diferentes.
O polimorfismo utiliza três técnicas para criar membros com o mesmo nome :
1. Early Bound – Os objetos early bound permitem que o compilador aloque memória
suficiente para o objeto e execute otimizações antes que o aplicativo seja executado. Quando
uma variável declarada com um tipo de dados específico recebe um objeto do mesmo tipo
então é considerado um objeto Early Bound.
2. Late Bound – Os objetos late bound permitem que o compilador faça uma referência ao
objeto na memória entretanto perde quase toda as otimizações de um objeto early bound.
Quando uma variável declarada com um tipo de dados Object (Universal) recebe um objeto
qualquer, então é considerado um objeto Late Bound.
De forma resumida os objetos Early Bound é o processo mais eficiente para o compilador, e,
portanto deve ser sempre utilizado ao invés dos objetos Late Bound.
Imports System.IO
'...
' Cria uma variável do tipo FileStream.
Dim FS As FileStream
' Atribui um novo objeto a essa variável.
FS = New FileStream("C:\tmp.txt", FileMode.Open)
Observe que o código acima utiliza uma variável explicitamente declarada com o tipo de objeto
FileStream da classe System.IO. Em seguida o objeto a ser atribuído é um arquivo de texto tabular
que é exatamente do mesmo tipo que a variável foi declarada.
85
A variável FS foi declarada para receber um objeto do tipo texto, além disso é uma cópia da classe
FileStream da plataforma .NET Framework.
A técnica para criar um objeto Early Bound é declarar um objeto de um tipo específico também
conhecido como criar um objeto Totalmente qualificado. Um objeto totalmente qualificado deve ter
a sintaxe : EspaçoNomeado.NomeDaClasse.NomeDoObjeto, que é semelhante ao caminho de
arquivo de Texto (C:/Meus Documentos/MeuTexto.txt).
No exemplo acima, foram criadas 3 variáveis do tipo Object que aceitam qualquer tipo de dados do
sistema. Em seguida foram atribuídos instâncias de uma automação do Excel, arquivo, planilha e etc.
Observe que as variáveis não foram declaradas de um tipo específico de dados ou classes, mas com
um tipo de dados genérico como o tipo Object.
O compilador precisa “descobrir” qual o tipo de dados do objeto e fazer uma referência na memória
para esse objeto recém criado.
Para criar uma cópia de uma classe é obrigatório utilizar a palavra chave New que explicitamente
cria um objeto antes de ser usado. Com New o sistema é preparado para alocar memória para um
objeto. Exemplo :
O primeiro exemplo simplesmente declarou uma variável como cópia de um botão de comando.
Entretanto a variável Button1 ainda contém o valor Nothing até que o desenvolvedor atribua um
objeto a variável como no exemplo abaixo :
Ainda no segundo exemplo, o código declara uma variável e atribui uma cópia de um botão de
comando. A variável Button2 realmente contém o objeto Botão de comando pois utilizou-se da
palavra chave New.
86
Todos os objetos consomem memória e recursos do sistema especialmente quando são criados
através da palavra chave New. Entretanto a tecnologia .NET Framework se responsabiliza em
desalocar automaticamente da memória todos os objetos que não estão em uso sem nenhuma
intercessão do desenvolvedor.
A palavra chave Nothing é usada para indicar que uma variável de objeto não contém referência a
nenhum objeto. Além disso é possível atribuir Nothing a objetos explicitamente para torná-los
disassociados, isto é sem referência alguma a outro objeto. Isto não implica dizer que a memória
ficará livre desse objeto imediatamente, pois como já foi dito o Garbage Collection se encarregará
dessa tarefa em seu tempo. Exemplo :
Por outro lado há alguns objetos que possuem os métodos Dispose e Finalize que liberam recursos
muito dispendiosos para o sistema imediatamente. Exemplo :
MeuObjeto.Dispose
Para trabalhar com grupos de objetos, simplesmente crie uma matriz com o tipo do objeto desejado.
Exemplo :
No exemplo acima foi criado uma variável matriz de 11 elementos de um tipo de dados MeuObjeto.
Em seguida dentro de um loop, foi referenciado o objeto para cada índice da matriz, pois a variável
foi declarado sem a palavra chave New.
A técnica de melhor desempenho para trabalhar com grupos de objetos é o objeto Collection
(Coleções). Exemplo :
No código acima, foi inicializada uma variável de objeto Coleção para receber um único objeto
processado no procedimento CrieOObjeto.
87
Todas as propriedades e métodos de matrizes e coleções são utilizados normalmente conforme
explicado em capítulos anteriores.
É possível determinar o tipo de objeto que uma variável genérica pertence através de três formas :
1. Função TypeName – Retorna uma string que indica o nome da classe que uma variável de
objeto pertence.
2. Operador TypeOf...Is – Testa um tipo de objeto efetuando uma comparação entre eles,
retornando True se for de um tipo específico. Esse operador é muito mais rápido que a função
TypeName.
3. Função CallByName - Permite usar uma string para executar um determinado método ou
propriedade de um objeto em fase de execução (Run Time).
If TypeOf Ctrl Is Button Then ‘Testa se uma variável Objeto é do tipo Botão de Comando
MsgBox("Esse controle é um botão.")
End If
Observe com atenção que o operador TypeOf...Is sempre retorna True quando um objeto é do tipo
específico ou de uma classe derivada de um tipo específico. Por isso quando se testa uma variável do
tipo Integer ou String por exemplo, isto implica dizer que ambas os tipos de dados são herdados de
uma classe chamada System.Object, o operador TypeOf...Is sempre retorna True.
A função CallByName é freqüentemente utilizada para acessar objetos do tipo COM e objetos do
tipo .NET. Esta função permite que o desenvolvedor possa descobrir as propriedades e métodos de
um objeto em fase de criação (Design Time) simplesmente enviando strings para o objeto e
esperando que seja executado a operação sem a preocupação em saber se os dados enviados são do
tipo esperado pelo método ou propriedade do objeto.
Onde :
Class Matemática
Function SquareRoot(ByVal X As Double) As Double
Return Math.Sqrt(X)
End Function
Function InverseSine(ByVal X As Double) As Double
Return Math.Atan(X / Math.Sqrt(-X * X + 1))
End Function
Function Acos(ByVal X As Double) As Double
Return Math.Atan(-X / Math.Sqrt(-X * X + 1)) + 2 * Math.Atan(1)
End Function
End Class
‘se digitar “64” na caixa de Texto TextBox1 e digitar “SquareRoot” na caixa de Texto TextBox2 e
‘acionar o procedimento CallMatemática, o código acionará a função SquareRoot da classe
‘Matemática e retornará o resultado 8.
NO exemplo acima, foi criado uma classe chamada Matemática com 3 membros de dados que
realizam cálculos matemáticos. Em seguida foi criado um procedimento que chama a classe
matemática através da função CallByName avaliando os dados digitados nas caixas de texto 1 e 2.
A função CallByName tem desempenho muito pior do que qualquer outro procedimento Late Bound
visto anteriormente, além disso pode afetar drasticamente o desempenho do aplicativo final.
2.18.5 - Classes
O código por trás dos objetos é chamado de classes e definem as propriedades, métodos, campos e
eventos desses objetos. De fato, classes são as estruturas dos objetos enquanto que os objetos são as
instâncias das classes.
Para criar uma classe utilize a estrutura Class ... End Class com o nome da classe desejada.
Exemplo:
End Class
89
É possível criar classes internas para as janelas quanto projetos exclusivamente para construir classes
gerais. Para isso basta usar o menu do Visual Studio .NET para criar novos projetos ou adicionar
novos itens de classe para o projeto.
Sempre que necessário utilize o comando Imports para acessar as classes .NET, digitando-o sempre
no início do código fonte da classe. Por exemplo :
Imports Microsoft.Win32
End Class
Para criar campos simples na classe declare variáveis com os modificadores de acesso. Exemplo :
Imports Microsoft.Win32
End Class
Os campos acima foram declarados com Private, portanto só podem ser acessados de dentro da
classe, conforme as regras de escopo. Os campos são úteis para trabalharem em conjunto com as
propriedades, essa técnica é recomendada para todos os procedimentos com classes.
As propriedades são ligeiramente diferentes dos campos conforme explicado em capítulos anteriores.
Portanto para criar novas propriedades utilize a estrutra Property ... End Property declarados com
os modificadores de acesso e especificando um nome para a propriedade. Exemplo :
Imports Microsoft.Win32
End Class
No exemplo acima foi criada uma propriedade chamada Nome que recebe um argumento Valor e
atribui diretamente para a variável-campo localNome declarada anteriormente, além disso pode
retornar esse valor simplesmente chamando novamente a variável localNome. Observe que a palavra
90
chave Get permite somente ler um valor de propriedade enquanto que Set permite atribuir um valor
para uma propriedade.
Conclui-se que é necessário criar variáveis locais para armazenar os valores de propriedades e
permitir a execução de cálculos mais abrangentes.
Para definir métodos (ações que a classe executa) utilize a estrutura de procedimentos simples Sub ...
End Sub declarados com os modificadores de acesso para controlar o escopo, além disso, informe
sempre o nome do método. Exemplo :
Imports Microsoft.Win32
End Class
Como visto em capítulos anteriores, um procedimento que não retorna valores dentro de classes é
chamado de método, enquanto que funções sempre retornam valores.
Quando uma classe é invocada pela primeira vez e o objeto baseado nessa classe é criado, há um
código especial que é executado automaticamente dentro de todas as classes denominado
Construtor. O construtor permite a execução de qualquer código que se faça necessário para
inicializar variáveis, limpar estruturas, criar outros tipos de controles e tantos outros procedimentos,
assim o construtor é o primeiro procedimento a ser executado pela classe.
O Construtor pode ou não receber parâmetros assim como qualquer procedimento simples, para
codificar um construtor utilize a estrutura Sub New ( ) ... End Sub. Exemplo :
Imports Microsoft.Win32
91
Private localNome as string
Private localEndereço as string
End Class
Como mostrado no exemplo acima, o construtor Sub New ( ) não tem nada de especial apenas limpa
os campos internos e exibe uma mensagem inicial. Observe que o construtor é similar aos eventos
Initialize do VB 6.0.
Além disso toda classe deve possuir um Destrutor que como o próprio nome indica é usado para
criar um código de limpeza geral. Diferentemente do Construtor, o Destrutor é o último código a ser
executado na classe, geralmente no momento que a classe for destruída na memória.
Para criar um destrutor personalizado utilize a estrutura Protected Overrride Sub Finalize ( ) ...
End Sub informando sempre o nome do destrutor a ser criado. Exemplo :
Imports Microsoft.Win32
92
End Sub
End Class
Observe ainda que a sintaxe para criar um destrutor deve obrigatoriamente incluir o comando
MyBase.Finalize( ) que é atribuído automaticamente pelo sistema.
Tanto classes como módulos Standard no VB .NET são referenciadas na memória e encapsulam
itens em sua implementação, mas são diferentes quanto a forma que são acessados. As classes são
instanciadas no código e uma vez criadas cada cópia tem sua execução própria independente se
existe outra cópia em execução. Enquanto que Módulos Standard não são instanciados e dependem
unicamente da cópia em execução.
Isto significa que se uma variável de um Módulo Standard é alterado via código na cópia em uso,
todos os outros códigos que estão utilizando o mesmo Módulo deverão ter essa alteração em leituras
subseqüentes. Ao passo que se um item de uma classe é alterada para uma cópia, qualquer outra
cópia da classe não sofrerá nenhum tipo de influência, pois cada uma terá sua própria execução.
A vida útil de um Objeto começa quando o objeto é criado com a palavra chave New. Alguns objetos
possuem tarefas de execução inicial que são controlados pelo VB .NET através de um procedimento
chamado Construtor.
A vida útil de um Objeto é encerrando quando o objeto é finalizado pelo código de chamada e é
liberado da memória pelo Common RunTime Language (CLR). O VB .NET controla a liberação dos
recursos do sistema através do procedimento chamado Destrutor.
93
Os procedimentos Sub New e Sub Finalize inicializam e finalizam os objetos substituindo os antigos
eventos Class_Initialize e Class_Finalize do VB 6.0. Toda vez que um objeto é criado, o
procedimento dentro de Sub New é invocado automaticamente pelo sistema antes de qualquer outro.
Além disso se o desenvolvedor não cria o procedimento Sub New, o VB .NET por sua vez cria
automaticamente esse procedimento.
Antes de liberar um objeto da memória o CLR do VB .NET chama o método Finalize (Destrutor)
automaticamente para os objetos que possuem este procedimento que pode, por exemplo salvar e
fechar arquivos necessários.
Há classes que utilizam recursos do Windows que não podem ser gerenciados pelo CLR do VB
.NET, como por exemplo os handles da API do Windows e conexões à Banco de dados. Nessas
situações a classe precisa implementar seu próprio Garbage Collection (Coletor de Lixo) utilizando
uma classe do VB .NET chamada interface IDisposable.
A interface IDisposable tem somente um método chamado Dispose que pode liberar recursos do
sistema e fechar conexões a Banco de dados, entretanto o método Dispose não é invocado
automaticamente, é necessário que o Cliente (o desenvolvedor que estiver utilizando a classe) chame
o método explicitamente quando finalizar a utilização do objeto.
Há um atraso entre quando o objeto é finalizado pelo cliente e quando o CLR libera-o da memória,
pois não há como saber quando este último procedimento será executado, portanto nesta situação um
objeto é chamado de non-deterministic lifetime (tempo de vida indeterminado), assim o Destrutor
Finalize pode não ser executado imediatamente quando o objeto perde o escopo (é finalizado).
Outro aspecto interessante é que o Garbage Collection do CLR não uitliza mais a palavra chave
Nothing para liberar recursos da memória, ao passo que outras versões do VB precisavam de
Nothing para liberar recursos imediatamente da memória. A palavra chave Nothing deve ser usado
no VB .NET somente quando os objetos tiverem uma vida útil longa demais afetando o tempo que o
CLR irá liberar o objeto da memória.
É possível criar um construtor com um ou vários parâmetros da mesma forma que se cria parâmetros
para procedimentos simples. Exemplo :
Quando se cria uma classe derivada de uma classe básica é necessário incluir na primeira linha do
construtor da classe derivada uma chamada ao construtor da classe básica se, e somente se o
construtor da classe básica tiver parâmetros. Por outro lado se o construtor da classe básica não tiver
94
parâmetros o Run Time do VB .NET chama-o automaticamente sem a intervenção do
desenvolvedor-Cliente. Exemplo :
Observe que a palavra chave MyBase é usada para fazer referência a classe básica.
Class ClasseBásica
Implements IDisposable
Public Sub Dispose() Implements IDisposable.Dispose
' Código qualquer para limpeza.
End Sub
End Class
Class ClasseDerivada
Inherits ClasseBásica
Implements IDisposable
Private handle As IntPtr ' Uma variável de estrutura que faz referência a um recurso qualquer
Private otherRes As OtherResource ' Outro recurso qualquer.
Private disposed As Boolean = False
95
‘Libera alguns recursos (exceto aqueles que ainda não foram liberados) e dá
‘a chance da classe básica finalizá-lo
Overloads Overrides Sub Finalize()
LiberarRecursos()
MyBase.Finalize()
End Sub
‘Sempre que utilizar Dispose é necessário verificar o estado de disposed para interceptar
‘uma exceção
Public Sub VerificaDispose()
If disposed Then
Throw ObjectDisposedException("ResWrapper")
End If
End Sub
End Class
No código acima foi criada uma classe básica que possui um método Dispose que conforme
explicado anteriormente libera explicitamente os recursos do sistema que não são gerenciados pelo
CLR, como por exemplo APIs do Windows.
Em seguida foi implementada uma classe derivada da classe básica que possui um construtor Sub
New que inicializa alguns objetos baseados em APIs (handles e etc). Quando a classe é inicializada o
VB .NET chama o construtor Sub New da classe básica automaticamente, mesmo que não tenha sido
implementado em código.
A classe Garbage Collection possui um método chamado SupressFinalize que solicita ao sistema
não invocar o método Finalize da classe derivada para permitir que a classe básica possa finalizar a
operação.
O fragmento de código acima demonstra a abertura e fechamento de uma conexão de banco de dados
em ADO.
96
O exemplo abaixo demonstra o uso de um construtor e um destrutor :
Sub FaçaAlgumaCoisa()
' Código que faz alguma coisa.
End Sub
Sub TesteConstrutoresEDestrutores()
Dim X As Integer = 6
Dim AnObject As New ClasseDerivada(X)
97
' Código qualquer que usa o objeto
AnObject.FaçaAlgumaCoisa()
' Testa o construtor parametrizado.
MsgBox("O valor de ThisProperty após ser inicializado" & _
" pelo construtor é " & AnObject.ThisProperty)
' Executa o método Dispose quando o objeto não for mais utilizado
AnObject.Dispose()
End Sub
Para criar um campo na classe simplesmente declare uma variável com o modificador de acesso
Public, exemplo :
Class ThisClass
Public ThisField As String
End Class
Observe porém que os Campos não oferecem o nível de segurança e controle das propriedades.
1. Use sempre variáveis locais para armazenar os valores das propriedades, pois as propriedades
em si não conseguem alocar os valores por si próprio. Além disso as variáveis locais
protegem os valores das propriedades de qualquer modificação direta. Declare as variáveis
locais sempre com Private.
2. Utilize os modificadores Public ou Shared junto com a palavra chave Property para iniciar
o bloco de propriedades.
3. Dentro do bloco, utilize a palavra chave Get para retornar o valor da propriedade e a palavra
chave Set para atribui um novo valor a propriedade. Set sempre recebe um parâmetro
normalmente chamado de Value.
4. Sempre finalize as propriedades com End Get e End Set.
5. Termine o bloco com End Property.
Class MinhaClasse
Private m_PropVal As String
Public Property Um() As String
Get
Return m_PropVal ' Retorna o valor da variável local.
' pode-se usar também a sintaxe Um = PropVal para retornar o valor a propriedade
End Get
Set(ByVal Value As String)
m_PropVal = Value ' Armazena o valor em uma variável local.
End Set
End Property
End Class
98
A técnica geral é sempre fazer uma instância da classe e atribuir um valor à propriedade, no caso
acima Um, em seguida a classe recebe o valor no argumento e atribui esse valor a variável local que
armazenará o valor até que a classse seja finalizada.
2 – Propriedades somente-leitura
Para criar propriedades somente-leitura não utilize a palavra chave Set. Para criar propriedades
somente-gravação não utilize a palavra chave Get. Exemplo :
Class MinhaClasse
Private m_PropVal As String
ReadOnly Public Property Um() As String
Get
Return m_PropVal ' Retorna o valor da variável local.
' pode-se usar também a sintaxe Um = PropVal para retornar o valor a propriedade
End Get
End Property
End Class
No exemplo acima a classe básica possui uma propriedade chamada UM que é somente leitura pois
não existe a palavra chave Set, além disso é preciso criar um código que inicialize o valor da
propriedade Um antes de retorná-la.
Os métodos de uma classe são todos os procedimentos Sub ou Function declarados dentro dessa
classe. Como já foi visto Funções retornam valores mesmo dentro de classes enquanto que
procedimento Sub não retornam valores.
Os métodos da classe devem ser construídos utilizando os modificadores de acesso assim como se
faz com um procedimento normal. Exemplo :
Class MinhaClasse
Public Sub MensagemDeBomDia ( )
Dim Mensagem as string
Mensagem = “Olá, Tenha um bom dia”
Msgbox (Mensagem)
End Sub
99
(Sub e Function) fossem declarados como o modificador de acesso Private, então o código só estaria
disponível para a chamada interna da classe, isto é somente o código da própria classe poderia
utilizar os procedimentos.
Essa técnica faz parte do encapsulamento e protege a implementação da classe de acessos externos.
Assim somente o criador da classe saberá que essas funções ou Sub existem e serão utilizadas
somente dentro da própria classe.
4 – Membros Shared
Os membros Shared (ocultados) podem ser invocados sem criar uma instância da classe. Exemplo :
Class MinhaClasse
Shared Sub MensagemDeBomDia ( )
Dim Mensagem as string
Mensagem = “Olá, Tenha um bom dia”
Msgbox (Mensagem)
End Sub
End Class
Sub Teste( )
Dim MinhaVariável as MinhaClasse ‘Não precisa utilizar a palavra chave New
MinhaVariável.MensagemDeBomDia( )
End Sub
No exemplo acima a classe MinhaClasse possui um procedimento Shared que pode ser invocado sem
utilizar a palavra chave New que cria uma instância da classe.
Os membros Shared são úteis quando o desenvolvedor deseja que um método (Sub ou Função) não
esteja associada com uma instância da classe, isto é o método esteja disponível mesmo sem o uso de
New.
As propriedades e métodos são similares na sua construção porque podem receber parâmetros.
Entretanto as propriedades podem receber parâmetros e atribuições com o sinal de atribuição,
enquanto que os métodos não podem receber novos valores com o sinal de atribuição, somente
através do argumento do parâmetro:
No exemplo acima não é possível atribuir um novo valor para o Método1 sem que seja através do
argumento NovoNúmero.
100
No exemplo acima, foi utilizada a propriedade Default Text de uma caixa de texto simples, assim o
desenvolvedor não precisa nomear a propriedade como por exemplo TextBox.Text = “Olá”.
• Para criar uma propriedade Default utilize a palavra chave Default antes de definir a
propriedade.
• Toda classe só pode ter uma propriedade padrão
• Uma propriedade Default (Padrão) não pode ser Shared ou Private.
• Se uma propriedade Default é overloaded, todas as propriedades resultantes com o mesmo
nome serão Default
• As propriedades Default devem aceitar pelo menos um argumento.
Exemplo :
Class Class2
' Define a variável local para armazenar o valor da propriedade
Private PropertyValues As String()
' Define a propriedade padrão.
Default Public Property Propriedade1(ByVal Index As Integer) As String
Get
Return PropertyValues(Index)
End Get
Set(ByVal Value As String)
If PropertyValues Is Nothing Then
' A matriz contém Nothing que é acessada pela primeira vez.
ReDim PropertyValues(0)
Else
' Redimensiona a matriz para armazenar os novos valores
ReDim Preserve PropertyValues(UBound(PropertyValues) + 1)
End If
' Value é uma variável implícita declarada pelo VB .Net que contém o valor
‘ da atribuição
PropertyValues(Index) = Value
End Set
End Property
End Class
O exemplo acima cria uma classe que possui uma propriedade Default que é uma matriz de
elementos strings, a cada atribuição a matriz é redimensionada automaticamente.
Para acessar uma propriedade padrão basta abreviar o código escrito. Exemplo :
Observe que sem Overloaded seria preciso criar nomes diferentes para cada procedimento que faça a
mesma coisa.
A palavra chave Overloaded é opcional, entretanto uma vez usada todos os outros membros também
deverão usar explicitamente Overloaded.
Quando uma classe derivada utiliza overloaded de um membro herdado de uma classe básica, isto é
sobrecarrega um método ou propriedade de uma classe básica, esse método ou propriedade criado
será usado ao invés do método da classe básica. Esse processo é conhecido como Shadowing por
nome e Assinatura (ocultação).
Observe com atenção que quando a palavra chave Overloaded é usado em processo Shadowing por
Nome e Assinatura o membro overloaded implementado na classe derivada substitui o membro
implementado na classe básica, entretanto os outros membros overloaded na classe básica estarão
disponíveis para a instância da classe derivada.
Ao passo que se a palavra chave Overloade for omitida em um processo Shadowing então o membro
overloaded implementado na classe derivada ainda substitui o membro implementado na classe
básica, só que os outros membros overloaded da classe básica não estarão disponíveis para a
instância da classe derivada.
As classes derivadas herdam todos os métodos e propriedades de uma classe básica, entretanto há
casos em que os membros de uma classe básica precisam ser modificados completamente para o uso
de uma classe derivada.
O overriding (substituição) permite criar uma nova implementação de métodos e propriedades para
serem usados na classe derivada.
Exemplo :
Class Pagamento
Overridable Function PagarEmpregados(ByVal HorasTrabalhadas As Decimal, _
ByVal Taxa As Decimal) As Decimal
PagarEmpregados = HorasTrabalhadas * Taxa
End Function
End Class
Class BonusPagamento
Inherits Pagamento
Overrides Function PagarEmpregados(ByVal HorasTrabalhadas As Decimal, _
ByVal Taxa As Decimal) As Decimal
' A linha seguinte chama o método original da classe básica e modifica o valor retornado
PagarEmpregados = MyBase.PagarEmpregados(HorasTrabalhadas, Taxa) * Bonus
End Function
End Class
Sub ExecutarPagamento()
Dim PagamentoItem As Pagamento = New Pagamento()
Dim BonusPagamentoItem As New BonusPagamento()
Dim HorasTrabalhadas As Decimal = 40
O exemplo acima define uma classe básica Pagamento e uma classe derivada BonusPagamento que
substitui um método da classe básica PagarEmpregados. Em seguida foi criado um procedimento que
testa as duas classes fazendo uma referências à classe básica e a classe derivada.
Concluindo, overrides substitui os membros de uma classe básica alterando a forma com que o
procedimento executa uma tarefa. Ao passo que overloaded sobrecarrega os membros de uma
classe básica modificando os parâmetros do membro.
Os eventos são sinais que um aplicativo enviam quando algo importante acontece. Para declarar
eventos dentro de classes, propriedades, módulos e interfaces utilize a palavra chave Event.
Exemplo:
103
Event AnEvent(ByVal EventNumber As Integer)
Um evento envia uma mensagem para o sistema, o ato de enviar uma mensagem é chamado de
raising (disparando) eventos. Utilize o comando RaiseEvent para disparar um evento :
RaiseEvent AnEvent(EventNumber)
Os eventos devem ser disparados no escopo onde foram declarados, isto é dentro de um
procedimento; dentro de uma função; dentro de uma propriedade, etc, e nunca poderão ser
disparados em outro lugar diferente.
Qualquer objeto capaz de disparar um evento é chamado de Event Sender (Emissor de eventos) ou
Event Source (Fonte de eventos), as janelas, controles e objetos criados pelo usuário são exemplos
de Emissores de Eventos.
Os Event Handler (Manipuladores de Eventos) são procedimentos que são chamados quando um
evento correspondente ocorre, normalmente a sintaxe de um manipulador de evento é
NomeDoControle + Underscoree + NomeManipuladorEvento. Não é possível utilizar uma função
como manipulador de evento, pois um manipulador de evento não pode retornar um valor. Por
exemplo:
Para que um manipulador de evento se torne útil é preciso associar esse manipulador com o próprio
evento utilizando os comandos Handles ou AddHandler. As palavras chaves WithEvents e
Handles são as formas tradicionais para criar eventos em classes.
Para adicionar eventos a uma classe utilize o comando Event seguido pelo nome do evento e seus
parâmetros. Exemplo:
Os eventos não podem retornar valores; não podem possuir parâmetros opcionais e não podem
possuir argumentos ParamArray.
No momento em que se cria um evento para a classe, o objeto dessa classe, agora pode disparar um
evento específico. Para que um evento possa realmente ocorrer é preciso utilizar o comando
RaiseEvent, além disso as palavras chaves Handles e AddHandler associam este evento a um
manipulador de eventos. Uma classe derivada não pode disparar eventos de uma classe básica.
A palavra chave WithEvents permite criar variáveis da classe ou de objetos de módulo que podem
ser usados com a clásula Handles para manipular Eventos, seguindo estes passos :
104
2. Escolher o nome dessa variável na lista de objetos na janela Editor de códigos do Visual
Studio .NET.
3. Escolher o evento da lista de eventos criados na janela do Editor de códigos do Visual Studio
.NET.
4. Adicionar um código para esse manipulador de evento.
‘Declara a variável com WithEvents que vai ser o objeto com o manipulador de eventos
Public WithEvents var As Classe1
var.Somar()
End Sub
No exemplo acima, observe que o VB .NET cria automaticamente o manipulador de evento para a
variável var, além disso adiciona automaticamente Handles que vai associar o evento Iniciar com a
variável var.
Portanto WithEvents permite criar uma variável da classe que atuará como o objeto que possui os
eventos, isto é a fonte de dados.
Para criar eventos dinamicamente conectados a manipuladores de eventos basta seguir os passos
seguintes :
1. Criar uma variável do tipo da classe desejada, podendo ser uma variável local.
105
2. Usar o comando AddHandler para informar o nome do emissor do evento (event sender)
junto com o operador AddressOf que informa o nome do manipulador de evento desejado.
Qualquer procedimento pode ser um manipulador de evento, desde que tenha os parâmetros
necessários.
3. Adicionar o código para o manipulador de evento.
O exemplo acima reutiliza a classe do exemplo anterior mas cria uma variável local que vai atuar
como o objeto emissor de eventos. Além disso utiliza um ponteiro para um manipulador de eventos
personalizado varIniciar_Evento que não foi criado automaticamente pelo VB .NET.
No exemplo acima reutiliza os exemplos anteriores e desconecta a variável emissor de eventos “var”
do manipulador de eventos varIniciar_Evento.
As classes derivadas podem manipular eventos disparados pela classe básica utilizando os comandos
Handles MyBase. Siga os passos a seguir para completar essa operação :
106
Public Class Classe1
Public Event SE(ByVal i As Integer)
' colocar métodos e propriedade aqui.
End Class
Os dois comandos acima são usados em pares para declarar um evento e especificar um manipulador
de eventos. As variáveis declaradas com WithEvents disparam eventos que podem ser manipulados
por qualquer procedimento informado na cláusula Handles. Assim é possível criar um manipulador
único para diversos eventos. Exemplo :
Dim WithEvents EClass As New EventClass() ' Declara uma variável com WithEvents
Sub TestEvents()
EClass.DisparaEventos()
End Sub
' Declara um manipulador de eventos que manipula diversos eventos ao mesmo tempo.
Sub EClass_EventHandler() Handles Eclass.XEvent, Eclass.YEvent
MsgBox("Evento recebido.")
End Sub
Class EventClass
Public Event XEvent()
Public Event YEvent()
Sub DisparaEventos() 'Dispara dois eventos manipulados por EClass_EventHandler.
RaiseEvent XEvent()
RaiseEvent YEvent()
End Sub
End Class
O exemplo acima cria uma classe EventClass que possui dois eventos XEvent e YEvent, além de um
método DisparaEventos que dispara os dois eventos simultaneamente. Em seguida foi criado um
código para o manipulador de evento para os dois eventos simultâneos.
Os comandos WithEvents e Handles é a melhor opção para declarar eventos. Entretanto possui
algumas limitações :
• Não se pode declarar variáveis genéricas com WithEvents, é obrigatório especificar o nome
da classe que possui eventos.
• Não se pode criar matrizes de variáveis com WithEvents.
• Não é possível associar múltiplos eventos para um simples evento
O comando AddHandler possui dois parâmetros : o primeiro informa o nome do evento junto com o
emissor do evento e o segundo é o operador AddressOf que delega o controle para um procedimento
específico.
Delegar é um recurso que permite que objetos possam ser usados para chamar os métodos de outros
objetos. O método delegar é também conhecido como Ponteiro de funções de segurança (type-safe
function pointers) que são similares aos ponteiros de funções de linguagens como C++.
O VB .NET utiliza delegate ao invés de ponteiros de funções que são tipos referência da Classe
System.Delegates, que podem fazer referências tanto a métodos Shared ( que não precisam de
instâncias de classes) quanto a métodos padrões ( que precisam de intâncias de classes ).
Delegar é útil principalmente em eventos, pois um objeto que dispara eventos pode chamar diversos
manipuladores para cada situação diferente. O comando AddHandler cria um processo Delegar que
chama o manipulador de evento apropriado e O VB .NET cuida de todos os detalhes deste processo.
Outro comando que executa um processo delegar é o comando Event que implicitamente cria um
processo delegate, além disso o operador AddressOf cria uma instância (cópia) de um processo
Delegate.
É possível criar os próprios processos Delegate personalizados. Para declarar eventos que utilizam
um tipo de Delegates existente basta utilizar a sintaxe abaixo :
Para criar delegates com outras tarefas específicas, declare procedimentos com o Comando Delegate.
Toda classe que foi delegada possui o método Invoke que é utilizado para acionar o método
delegado.
108
End Class
End Class
O exemplo acima ilustra demonstra o uso de Delegate e AddressOf. De acordo com as definições
acima Delegate utiliza um objeto simples para acessar os métodos e membros de outros objetos,
assim o objeto “Contar” foi utilizado como base para acessar os métodos das classes 1, 2 e 3.
O código acima testa a melhor forma de exibir uma informação para o usuário, primeiro foi testado o
método “Contar1” que exibe um tipo de informação. Em seguida foi testado o método “Contar2” que
exibe a mesma informação, mas com um texto diferenciado, e por último “Contar3” exibe a última
informação mais diferenciada ainda.
109
Resumindo, Delegate permitiu no caso acima, escolher a melhor forma de exibição de texto para o
usuário, mas é claro que o código acima foi utilizado somente para ilustração.
Interfaces é um novo recurso do VB .NET que permite definir propriedades, métodos e eventos sem
implementação, isto é sem criar os códigos de cada membro. As interfaces definem somente o tipo
de membro que uma classe irá implementar por exemplo, Sub, Event, Function e Property.
Depois de definida uma interface, uma classe deve implementar livremente cada aspecto dessa
interface exatamente como ela foi definida. É possível adicionar novos recursos a qualquer momento
criando novas interfaces e novas implementações para essas classes.
No VB .NET as interfaces são criadas diretamente com o comando Interface e são implementadas
com o comando Implements. A Interface é definida usando os comandos Interface ... End
Interface, além disso é possível utilizar o comando Inherits que lista interfaces herdadas.
As interfaces não podem possuir nenhum comando ou código de implementação dentro da sua
definição, tais como Sub ... End Sub, Function ...End Function, Property.... End Property. Todas as
interfaces são Públicas (Public) por default, mas podem ser declaradas explicitamente com Protected,
Public, Private, Friend.
Para definir uma interface, basta utilizar a estrutura de comandos Interface ... End Interface
declarando um nome para essa interface, em seguida defina as propriedades, métodos e eventos
concernentes a essa interface. Exemplo :
No exemplo acima o código define uma interface chamada “MinhaInterface” em seguida define uma
propriedade chamada “MinhaPropriedade” que deverá ser implementada somente com os comandos
Property ... End Property. E finalmente a interface define uma função chamada “MinhaFunção”
que deverá ser implementada com os comandos Function ... End Function.
A palavra chave Implements é usada para implementar um membro de uma interface específica. O
comando necessita de uma lista de membros da interface separadas por ponto, para localizar o
membro específico da interface. Exemplo :
Além disso o comando Implements pode ser usado para criar uma implementação para múltiplos
métodos de uma interface, bastando separar as interfaces com vírgura. Exemplo :
110
Exemplo de criação e implementação de interfaces :
Interface Interface1
Sub sub1(ByVal i As Integer)
End Interface
Interface Interface2
Inherits Interface1 'Herda a definição da interface1.
Sub M1(ByVal y As Integer)
ReadOnly Property Num() As Integer
End Interface
111
No exemplo acima foram criadas duas interfaces 1 e 2 com métodos Sub1 e M1 além de uma
propriedade somente leitura “Num”. A implementação das interfaces foram feitas nas classes
ClasseImplementação1 e ClasseImplementação2, cada qual com uma mensagem diferente ao
usuário.
Interfaces é uma poderosa ferramenta de programação que permite separar a definição de um objeto
da implementação desse objeto. Assim esse recurso permite que a implementação seja feita
livremente por outras classes independentes entre si.
Interfaces são mais flexíveis do que herdar classes diretamente. A herança de classes possui um
problema, pois se a classe básica possui erros na implementação, as classes derivadas também a
terão.
Assim quando a correção do erro é feito na classe básica as outras classes derivadas podem não
funcionar corretamente, pois os métodos sobrecarregados (overloads) e substituídos (Overrides)
podem não ser compilados adequadamente.
A inteface resolve grande parte desses problemas publicando novas interfaces atualizadas. Além
disso as interfaces são mais flexíveis que herdar classes porque permitem criar códigos livres para
cada interface.
• Quando o aplicativo a ser construído não possua relacionamento entre objetos, mas que
possuam algumas funcionalidades semelhantes.
• Quando houver necessidade de meios mais flexíveis de programação do que os encontrados
entre classes básica e classes derivadas, isto é herança entre classes.
• Quando não é necessário herdar implementações de classes básicas, isto é herança entre
classes.
• Quando utilizar estruturas que não podem ser herdadas mas podem possuir interface.
Herança é um recurso do VB .NET que permite criar classes baseadas em outras classes já existentes.
A classe que serve de base é chamada de classe básica e a classe resultante é denominada classe
derivada.
A classe derivada herda todas as propriedades, métodos e eventos não privativos da classe básica,
podendo inclusive extender suas implementações. Além disso as classes derivadas podem substituir,
e sobrecarregar qualquer membro da classe básica.
Todas as classes do VB .NET são herdáveis por default. Para criar um classe derivada de outra classe
deve-se seguir as regras abaixo :
• Todas as classes são herdáveis exceto aquelas marcadas pela palavra chave NotInheritable.
112
• As classes derivadas podem ser criadas herdando somente uma classe básica por vez. Assim
não é possível fazer uma herança de múltiplas classes, entretanto múltiplas classes que
implementam interfaces podem facilmente suprir essa limitação.
• Os modificadores de acesso dos itens da classe derivada devem ser igual ou mais restritivas
que os modificadores de acesso dos itens da classe básica. Isto significa que se uma classe
básica for declarada como Friend, a classe derivada não pode expor a classe básica mesmo
que a classe derivada for declarada como Public. Assim a classe derivada deveria ser
declarada como Friend ou outro modificador de acesso mais restritivo.
• Para criar uma herança sempre inclua o comando Inherits.
Uma classe derivada pode modificar o comportamento dos métodos da classe básica substituindo a
implementação dos seus membros utilizando Overridden.Os modificadores abaixo controlam a
técnica do Overridden :
• Overridable – Permite que um método ou propriedade de uma classe básica possa ser
substituída (overridden) pela classe derivada.
• Overrides – Substitui um método ou propriedade Overridable de uma classe básica.
• NotOverridable – Evita que métodos e propriedades sejam substituídas (overriden) na classe
derivada. Todos os métodos e propriedades públicas são NotOverridable por default.
• MustOverride – Obriga que a classe derivada substitua (overrides) os métodos e
propriedades da classe básica. O modificador MustOverride deve ser usado em todas as
classes declaradas com MustInherit.
É possível chamar os métodos de uma classe básica mesmo que esteja sendo substituído na classe
derivada utilizando o comando MyBase. Exemplo :
Class ClasseDerivada
Inherits ClasseBásica
Public Overrides Function Calcular(ByVal Distância As Double, ByVal Tempo As Double) As
Double
' Chama o método da classe básica e modifica o valor retornado.
Return MyBase.Calcular (Distância, Tempo) * 2
End Function
End Class
• MyBase refere-se somente a classe básica, não é possível acessar membros privates da classe.
• MyBase é um comando e não um objeto, portanto não pode ser atribuído a variáveis nem ser
utilizado em comparações.
• MyBase pode se referir a classes básicas imediatas ou classes herdadas indiretamente.
• MyBase não pode invocar métodos MustOverride de classes básicas.
• MyBase não pode ser usado como auto-qualificador. Por exemplo
MyBase.MyBase.BtnOK_Click() ' Erro.
113
• MyBase não pode ser usado em módulos e não pode acessar membros Friend de classes
básicas de outros Assemblies.
MyClass chama um método original da classe corrente mesmo que tenha sido susbstituído por outra
implementação, é como se os métodos fossem declarados como NotOverridable. Exemplo :
Class ClasseBásica
Public Overridable Sub MeuMétodo()
MsgBox("Classe Básica")
End Sub
Public Sub UseMe()
Me.MeuMétodo() 'Usa a versão da classe chamada mesmo se for substituída (override)
End Sub
Public Sub UseMyClass()
MyClass.MeuMétodo() ' Usa esta versão do método e não a substituída (override)
End Sub
End Class
Class ClasseDerivada : Inherits ClasseBásica
Public Overrides Sub MeuMétodo()
MsgBox("Classe Derivada")
End Sub
End Class
Class TestarClasses
Sub Iniciar()
Dim TestObj As ClasseDerivada = New ClasseDerivada()
TestObj.UseMe() ' Exibe "Classe Derivada".
TestObj.UseMyClass() ' Exibe "Classe Básica".
End Sub
End Class
Observe também como o comando Inherits foi utilizado na implementação da classe Derivada.
114
Para utilizar a técnica da herança adicione o comando Inherits com o nome da classe básica. Esse
comando deve ser sempre a primeira linha de implementação da classe derivada. Exemplo :
Class Classe1
Sub Metodo1()
MessageBox.Show("Este é um método da classe básica.")
End Sub
Overridable Sub Metodo2()
MessageBox.Show("Este é um outro método da classe básica.")
End Sub
End Class
Class Classe2
Inherits Classe1 ‘Inherits deve ser sempre a primeira linha não comentada da implementação
Public Field2 as Integer
Overrides Sub Metodo2()
Messagebox.Show("Este é um método da classe derivada.")
End Sub
End Class
1. Use herança quando se deseja criar funcionalidades básicas que possam ser melhoradas nas
classes derivadas
2. Use Inteface em situações onde as funcionalidades sejam similares mas as implemetações
sejam completamente diferentes.
Há duas formas de criar um relacionamento entre classes, “É um” e “Tem um” relacionamento.
• “É um Relacionamento” – É uma classe derivada totalmente de uma classe básica, isto é a
classe derivada é do mesmo tipo da classe básica, possuindo os mesmos campos, métodos e
propriedades.
• “Tem um Relacionamento” – A classe derivada não é herda a classe básica, isto é alguns
membros da classe básica não devem ser herdados pela classe derivada. Assim não ocorre a
herança num tipo “Tem um Relacionamento”.
Exemplo :
No exemplo acima uma Classe denominada “Cliente” possui uma classe derivada “Cliente
Preferencial” que foi completamente herdada da classe básica. A classe “Cliente Preferencial” pode
possuir todos os membros de dados da classe “Cliente” pois é um cliente já cadastrado e em
atividade, portanto a hierarquia é conhecida como “É um Relacionamento”.
A classe denominada “Cliente Encaminhado” é um potencial cliente ainda não cadastrado e que não
comprou produto algum da loja, portanto não pode herdar os membros “Preferências” e “Último
Pedido” da classe básica. Assim essa hierarquia é conhecida como “Tem um Relacionamento”.
Para classes “Tem um Relacionamento” o melhor recurso é implementar Interfaces para alcançar o
objetivo proposto.
116
Todo código reutilizável é altamente recomendado pelo simples fato de não ter o trabalho de
codificar e testar todos os procedimentos novamente. Uma vez criado o código básico todos as outras
classes podem reutilizar o código incrementando outros procedimentos necessários.
Um exemplo típico é criar uma classe que implementa uma coleção de dados lidos de um banco de
dados, por exemplo uma tabela clientes, e permite o acesso a todas as informações na memória. Em
seguida uma classe derivada poderia manter a mesma coleção para a tabela clientes mas adiciona
uma outra coleção que lê os dados da tabela Pedidos e mantém na memória para posterior consulta.
Entretanto toda a reutilização de código pode possuir erros graves que só podem ser evitados em
sistemas bem desenhados.
Qualquer classe básica pode deixar a responsabilidade da implementação dos membros para cada
classe derivada. Assim todo o método poderá acomodar qualquer tipo de dados.
Essa técnica evita erros quando por exemplo um código da classe derivada deseja calcular uma taxa
de aumento para um produto em 2,5%, entretanto o método da classe básica só aceita números
inteiros. Assim para resolver o problema a classe básica definiria um método somente herdado para
ser implementado na classe derivada. Exemplo:
No exemplo acima, o desenvolvedor além de criar uma classe somente herdável, os itens
ValorTotalArredondado e ValorTotalArredondadoAMenor são definidos na classe básica Produtos
que poderão ser reutilizados nos cálculos das classes básicas descendentes.
Quando se cria uma classe básica é possível criar várias classes derivadas que herdam os recursos da
classe básica, assim a hierarquia de classes é formada pela criação de classes herdadas. Entretanto
classes que possuem hierarquias muito grandes e complexas dificultam a programação, portanto
como regra geral é necessário limitar os níveis de hierarquia até no máximo 6 (seis) níveis.
Um dos benefícios da herança é que as mudanças nas classes básicas podem afetar as classes
derivadas, entretanto nem todas as modificações podem ser feitas quando há dezenas de classes
derivadas da classe básica.
Quando o criador da classe básica altera o código de um de seus membros, os desenvolvedores que
criaram classes derivadas podem não conseguir recompilar a classe herdada com as novas
modificações.
117
Por exemplo, um classe básica foi criada com um campo para armazenar o código postal de ruas e as
classes derivadas herdaram esse campo de informação. Mais tarde foram feitas alterações na classe
básica para comportar mais 4 dígitos expandindo o número atual para 9 dígitos, entretanto as classes
básicas ainda permanecem com 5 dígitos.
Para que os desenvolvedores não precisem alterar o código das classes derivadas, é possível criar um
campo adicional na classe básica que armazene os 4 dígitos adicionais. Assim os aplicativos
poderiam ser atualizados sem alterar o código das classes derivadas, esse é o meio mais seguro e
eficaz de resolver tais problemas.
Todos os programas codificados com o Visual Studio .NET podem utilizar todas as classes da
plataforma .NET. Por exemplo classes que definem atributos podem herdar os recursos da classe net
System.Atributte, classes que definem componentes podem herdar recursos da classe net
System.ComponentModel.Component e assim por diante.
A tecnologia .NET além de possuir classes básicas prontas, permite que todo o software criado por
outras linguagens de programação sejam totalmente compatíveis entre si. Assim uma classe básica
criada com o Visual C# pode ser utilizada para criar classes derivadas em VB, que conseqüentemente
pode ser utilizado pelo C++ .NET.
Quase tudo criado pelo VB .NET involve objeto, além de strings, integers etc, que também podem
ser considerados objetos. Todos os objetos são herdados de uma classe básica da plataforma .NET
System.Object que possui código padrão para todos os objetos da plataforma. Todas as novas
classes herdam implicitamente (automaticamente) os recursos da classe System.Object,
portanto nunca será necessário herdar explicitamente a classe System.Object com o comando
Inherits.
Como já foi visto anteriormente, quando uma classe é criada o CLR – Common Language RunTime
(Runtime de linguagem comum) executa em primeiro lugar o código do método Sub New, também
conhecido como Construtor. Esse código pode desempenhar qualquer tarefa desejada tais como Abrir
Arquivos, abrir conexões de banco de dados, inicializar variáveis e outros mais.
Quando um classe derivada é criada, o construtor da classe básica é executada sempre em primeiro
lugar seguido pelo construtor da classe derivada. Isto acontece porque o construtor da classe derivada
possui a sintaxe MyBase.New ( ) que chama o construtor da classe imediatamente acima da
hierarquia.
Todas as classes derivadas irão invocar os construtores das classes imediatamente anteriores na
hierarquia, até chegar no construtor na classe de última hierarquia. Exemplo :
118
Quando o objeto não estiver mais em uso, o CLR chama o método Finalize (Destrutor) antes de
retirá-lo da memória. O código dentro de Finalize executa tarefas de limpeza, tais como salvar
informações, fechar arquivos, fechar conexões de banco de dados e outros mais.
O código em Finalize será executado sempre primeiro na classe derivada de última hierarquia até
chegar no código Finalize da classe básica. Isto porque a sintaxe MyBase.Finalize ( ) deve estar
sempre na última linha do código Finalize.
De fato, quando uma classe derivada é encerrada, o código de limpeza geral deve ser efetuada para
esta classe, pois poderá fechar arquivos, conexões e salvar configurações abertas por esta classe
somente. Em seguida será invocado o código de limpeza da classe de hirarquia anterior que também
efetuará limpeza geral para as tarefas executadas por essa classe. Exemplo :
119
2.18.11 – Polimorfismo
O polimorfismo é a habilidade de criar classes que possuam nomes, métodos e propriedades idênticas
mas funcionalidades diferentes.
O polimorfismo baseado em herança é quando os métodos e propriedades de uma classe básica são
overriden (substituídos) por outra implementação (outro código) na classe derivada.
O polimorfismo é a habilidade de chamar um método de um objeto sem conhecer a classe em que foi
derivado.
Sub TestPoly()
Dim Item1 As New BaseTax()
Dim Item2 As New CityTax()
ShowTax(Item1, 22.74)
ShowTax(Item2, 22.74)
End Sub
Sub TestarInterface()
Dim Retângulo2 As New Retângulo( )
Dim Triângulo2 As New Triângulo( )
ProcessarFigura(Triângulo2, 3, 14)
ProcessarFigura(Retângulo2, 3, 5)
End Sub
121
O exemplo acima cria uma interface que é implementada em duas classes diferentes. No
procedimento TestarInterface cada objeto utiliza seu método CalcularÁrea específico
Hierarquia de classes é a habilidade de criar classes derivadas que reutilizam código e adicionam
novas funcionalidades aos métodos já existentes da classe básica, com um máximo desejável de 6
(seis) níveis.
Para criar uma hierarquia de classes bem desenhadas é preciso seguir os seguintes conselhos :
• Crie uma hierarquia de classes começando com classes básicas mais gerais possíveis e
derivando classes cada vez mais específicas. Por exemplo quando se deseja criar uma
hierarquia de classes que modelam o hardware do computador, pode-se criar classes
derivadas com o nome de cada dispositivo como Monitor, teclado, mouse. Em seguida pode-
se criar classes derivadas nas próximas hierarquias com o nome de tipos de Monitores, tais
como MonitoresColoridos, MonitoresDigitais, etc.
• Prefira variáveis que possuam grande capacidade de armazenamento para facilitar quaisquer
mudanças de armazenamento no futuro. Por exemplo, quando uma classe requer usar uma
variável apenas do tipo Integer, então escolha o tipo Long mais abrangente.
• Somente exponha os itens que a classe derivada necessite, isto é utilize o declarador Public
com cautela, ao invés disso utilize Private para proteger os itens da classe básica que não
interessam a classe derivada.
• Os itens que serão necessário para a classe derivada devem ser marcados com o declarador
Protected, reduzindo o número de classes que serão dependentes desse item.
Como regra geral é imprescindível definir como os membros (propriedades, campos e métodos) da
classe deverão ser acessados, declarando-os com os modificadores de acesso, desta forma é possível
controlar como os membros serão usados. Conforme abaixo :
122
• Todos os membros internos da classe deverão ser declarados como Private, assim somente o
código dentro da classe em que foi definido, poderá acessar este membro.
• Todos os membros que deverão ser usados somente dentro da classe ou por classes derivadas
devem devem ser declarados com Protected. Assim esse membro só será acessível dentro do
código da classe que o definiu e dentro do código das classes derivadas dessa classe básica.
• Todos os membros que deverão ser acessados por módulos externos a classe, devem ser
declarados como Friends. Assim o membro poderá ser acessado somente por módulos que
fazem parte do projeto da classe.
• Todos os membros que deverão ser acessados por toda a hierarquia de classes deverão ser
declarados com Public.
Toda hierarquia de classes pode sofrer um problema chamado de Classes de base frágil (Fragile
base Classes) que significa que mudanças feitas na classe básica afetam todas as classes derivadas
obrigando a recompilação e redistribução dos componentes.
A hierarquia de classes pode sofrer mudanças desde a alteração das necessidades do software até a
ausência de algum elemento não codificado por esquecimento.
A melhor forma de evitar o problema Fragile base Classes é modificar somente a classe derivada,
mas quase sempre isso não é possível. De forma geral o problema não pode ser eliminado, mas
pode ser reduzido utilizando os seguintes recursos :
A tecnologia COM (Component Object Model) foi utilizada para criar componentes para o Sistema
Operacional Windows durante muitos anos, esses componentes variavam desde controles, arquivos
executáveis e até aplicativos para Windows 95, 98, Me, NT, XP e etc. A tecnologia COM permitia
que esses objetos pudessem expor suas propriedades, métodos e funções (chamados de interface)
para outros componentes e aplicativos.
Com a criação da plataforma NET, os aplicativos criados com a tecnologia .NET deverão substituir a
tecnologia COM, entretanto ainda hoje a maioria dos programas são escritos com COM, assim foi
criada a Interoperabilidade COM (Interop COM) no Visual Studio .NET para que os
programadores pudessem trabalhar normalmente com os componentes COM.
Todo o código criado pela plataforma NET é Código Gerenciado (Managed Code) que produz
MetaDados (MetaData) que são utilizados pelo CLR (Common language Runtime). Os dados
utilizados pelo aplicativo criado com a tecnologia NET são chamados de Dados gerenciados
(Managed Data) pois o arquivo Run Time da plataforma NET gerencia as tarefas relacionadas a
estes dados tais como gerenciamento de memória, verificação dos tipos de dados e etc.
Os componentes COM são códigos e dados não gerenciados que precisam ser acessados com a
Interoperabilidade da plataforma NET, através dos Assemblies.
123
Os Assemblies são componentes da plataforma Net que funcionam como coleções de versão,
construção, distribuição de um aplicativo simples. Na antiga versão do VB 6.0 existia a Type
Lybraries ou biblioteca de tipos que exibia as propriedades, métodos de um objeto COM, hoje em dia
os Assemblies possuem essa mesma função.
O VB .NET possui programas chamado Tlbimp.exe e Tlbexp.exe que importam e exportam objetos
COM respectivamente.
Os Interop Assemblies são um tipo de assemblie que agem como um intermediário entre os objetos
COM (não gerenciados) e os aplicativos .NET (gerenciados). Os Interop Assemblies utilizam um
processo chamado de Interoperalility marshalling (ordenação de interoperações) que analisa
automaticamente os parâmetros e tipos retornados de um objeto COM e transforma esses itens para
tipo de dados equivalente em um aplicativo .NET ou vice versa.
Para usar um objeto COM no aplicativo basta Adicionar uma referência ao objeto COM na janela
Project > Add Reference da IDE, em seguida crie um Interop Assemblie utilizando o comando
Imports na primeira linha de código do aplicativo.
É possível criar um Interop Assemblie utilizando a linha de comando, similar ao DOS, utilizando o
programa Tlbimp.exe com o caminho do objeto COM (dll, ou outros), além do projeto a ser usado e
o nome do Interop Assemblie a ser criado. Exemplo :
Um controle ACTIVEX é um componente COM que pode ser utilizado por páginas WEB ou por
aplicativos Desktop (aplicativos Cliente), que também pode ser utilizado pelo VB .NET basta
adicionar o controle na caixa de ferramentas do Visual Studio .NET IDE selecionando o menu Tools
> Customize Toolbox e escolher a aba COM components.
Para criar um projeto utilizando a tecnologia COM, basta escolher um novo projeto no VB .NET do
tipo CLASS Library e adicionar um item COM Class, em seguida adicione métodos, propriedades e
eventos e compile o programa.
É possível criar um projeto COM sem usar o item COM Class, esse tipo de projeto requer a criação
manual de uma classe COM. Basta escolher um novo projeto do tipo Class Library selecionar a
Página de propriedades do projeto (Clicando com o botão direito do mouse sobre a janela Solution
Explorer no nome do projeto) e escolhendo o item Build e finalmente marcando a caixa Register for
Com Interop.
Em seguida é necessário criar os atributos da classe ComClass, tais como a identificação da classe; a
identificação da Interface, a identifação dos eventos. Exemplo :
Para criar cada número de identificação, selecione o menu Tool > Create Guid > Registry Format em
seguida selecione o botão Copy para adicionar os número recém criados para a área de transferência,
e não esquecendo de remover as chaves entre os números.
124
Public Const EventsId As String = "2B691787-6ED7-401e-90A4-B3B9C0360E31"
Toda classe COM deve possuir um construtor não parametrizado, caso contrário a classe não será
registrada no Windows, para isso basta fazer isso :
Observe que não é possível utilizar um projeto COM gerado pelo VB .NET em outro aplicativo
VB .NET.
2.20 – Multithreading
Os aplicativos codificados com a tecnologia .NET podem executar várias tarefas simultaneamente
usando um processo chamado Multithreading (threading livres) que separa as tarefas em pedaços
separados em fila para execução no sistema operacional. Esse tipo de processamento melhora o
desempenho do aplicativo pois de um lado o aplicativo centraliza os procedimentos de validação de
entradas do usuário enquanto o sistema operacional executa outras tarefas de threads separados.
De forma mais resumida, um aplicativo Multithreading poderia validar as digitações feitas por um
usuário em um primeiro thread, e concomitantemente o aplicativo executaria complexos cálculos
matemáticos em um segundo thread junto com uma atualização do banco de dados em um terceiro
thread. Ao passo que um aplicativo de um simples thread, deveria aguardar a validação de dados em
seguida efetuaria complexos cálculos e somente após o términos dos processamentos anteriores
atualizaria o banco de dados.
Para criar um Thread, crie uma variável de classe Thread e utilize o operador AddressOf com o
endereço de um procedimento :
Cada Thread tem sua prioridade, isto é o tempo que o sistema operacional trata o processo como alta
prioridade enquanto os outros são tratados como de baixa prioridade. A propriedade Priority ajusta o
valor para essa prioridade. As enumerações possíveis para esse propriedade são (Do maior para o
menor) :
Enumeração
Highest
AboveNormal
Normal
125
BelowNormal
Lowest
Um thread pode ser divido em primeiro plano e segundo plano, os de primeiro plano são executados
indefinidamente enquanto que os de segundo plano ficam em fila. É possível mudar o estado de
segundo plano utilizando a propriedade IsBackground.
Uma vez um thread em execução, como no exemplo MyThread.Start( ), é possível mudar o seu
estado de execução utilizando a propriedade ThreadState que usa um ou mais itens da enumeração
System.Threading.ThreadState. Assim por exemplo é possível colocar um processo Thread em
modo de espera Thread.Sleep( tempo) onde tempo é um valor em milissegundos determinados ou
um Thread.Sleep (System.Threading.Timeout.Infinite) que só pode ser religado ou interrompido
por Thread.Interrupt.
Os threads do mesmo aplicativo trabalham sob o mesmo espaço de memória, e para evitar que um
thread utilize um mesmo dado de outro thread, é necessário utilizar sincronização. Um thread
independente pode ser sincronizado com outro thread diferente, assim quando um processo acaba o
outro inicia automaticamente e sincronizadamente. Por exemplo um thread executa um procedimento
que classifica um nome por ordem alfabética e um outro thread aguarda esta classificação para
depois utilizar os dados.
Os eventos são as formas mais comuns de sincronizar threads. Um thread dispara um evento e
sinaliza ao programa principal ou outro thread o estado do processamento.
O comando SyncLock permite sincronizar threads, evitando que múltiplos threads acessem o mesmo
dado compartilhado ao mesmo tempo. O código escrito entre o bloco SyncLock ... End SyncLock
fica bloqueado, assim o compilador executa de modo exclusivo todo o código dentro do bloco
SyncLock .. EndLock. Exemplo :
Class Cache
Private Shared Sub Add(ByVal x As Object)
SyncLock GetType(Cache)
End SyncLock
End Sub
Note que toda a expressão dentro do bloco SyncLock deve ser do Tipo Referência (veja
explicações nos capítulos anteriores), como por exemplo Classe, Delegate, Interface, Módulo ou
Matriz.
No exemplo anterior uma classe possui um thread exclusivo para o método Add e outro para
Remove, isto evita que um item seja removido enquanto ele ainda está sendo adicionado pela classe.
Outro recurso para sincronização é o método Thread.Join que determina se um thread terminou uma
tarefa antes que outro thread inicie outra tarefa. O método Join aguarda um tempo até que um thread
finalize a execução da tarefa, se a tarefa for completada o método Join retorna True, senão retorna
False.
126
O exemplo abaixo demonstra o uso de threading.
Option Compare Text ' Compara texto insensitivo (sem maiúsuculo ou minúsuclo).
' Use Option Compare Binary para procura sensitiva.
Sub ContarPalavras()
Dim f As System.IO.File
Dim mystream As System.IO.StreamReader
Dim mystr As String = " " ' Não permite Empty por isso foi colocado um espaço adicional
Try
mystream = f.OpenText(SourceFile) ' Abre um novo Stream.
' Faça até que stream retorne Nothing no final do arquivo
Do Until IsNothing(mystr)
mystr = mystream.ReadLine
WordCount += CountInString(1, mystr, CompareString)
LinesCounted += 1 ' Adiciona 1 ao contador de linhas.
' Dispara um evento que monitor ao progresso da pesquisa..
RaiseEvent Status(LinesCounted, WordCount)
Loop
Catch eof As IO.EndOfStreamException
' Nenhuma ação pois já chegou o final do arquivo.
Catch IOExcep As IO.IOException
' Algum tipo de erro ocorreu.
MsgBox(IOExcep.Message)
Dim mynumber As Integer
Finally
mystream.Close() ' Fecha o arquivo.
End Try
RaiseEvent FinishedCounting(WordCount)
End Sub
127
Private Function CountInString(ByVal StartingPoint As Integer, ByVal SourceString As String, _
ByVal CompareString As String) As Integer
' Função que conta o nr de vezes que uma palavra foi encontrada na frase.
' Se a palavra for encontrada a função processa recursivamente os strings restantes..
strloc = Strings.InStr(StartingPoint, SourceString, CompareString)
If strloc <> 0 Then
CountInString += 1
CountInString += CountInString(strloc + Strings.Len(CompareString), _
SourceString, CompareString)
End If
End Function
End Class
Sub IniciarThread()
Dim WC As New Palavras()
Me.WordsCounted.Text = "0"
' Configura os valores pois não é possível passar um procedimento que possui parâmetros..
WC.CompareString = Me.CompareString.Text ' A palavra a ser procurada.
WC.SourceFile = Me.SourceFile.Text ' O arquivo a ser procurado.
' Associa o manipulador de evento ao evento disparado pelo thread.
AddHandler WC.FinishedCounting, AddressOf FinishedCountingEventHandler
' Associa o manipulador de evento ao outro evento disparado pelo thread
AddHandler WC.Status, AddressOf LineCountEventHandler
' Cria efetivamente o Thread.
Thread = New System.Threading.Thread(AddressOf WC.ContarPalavras)
' Inicia o thread.
Thread.Start()
End Sub
128
Private Sub Cancel_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Cancel.Click
PararThread(Thread)
End Sub
O exemplo acima cria uma classe “Palavras” que irá fazer busca de palavras em um arquivo de
Texto. A classe possui um método “ContarPalavras” e “CountInString” que disparam eventos na
medida que encontram a palavra no texto.
Os manipuladores de evento atualizam caixas de texto de uma janela do aplicativo e avisam quando
o processo terminou. Observe que o procedimento “ContarPalavras” é executado em segundo plano
enquanto que outro procedimento poderia ser executado livremente, tal fato é comprovado bastando
clicar em um botão cancelar (veja Cancel_Click no exemplo acima).
O VB .NET permite manipular drivers, pastas e arquivos de 3 formas diferentes, através da classe
System.IO da plataforma .NET; das funções internas do compilador do VB ou através do objeto
FileSystemObject.
System.IO é uma espaço nomeado da plataforma .NET que possui várias classes que permitem
manipular arquivos e pastas. Um espaço nomeado é um local de trabalho (tipo diretório) da
plataforma .NET que agrupa classes que executam um tipo específico de tarefa. Para utilizar
determinada classe ou serviço é preciso se posicionar no respectivo espaço nomeado.
Exemplo :
129
' Move o ponteiro para o início do arquivo.
w.Seek(0, SeekOrigin.Begin)
No exemplo acima foi demonstrado a sintaxe básica de algumas classses, o objeto fs é uma cópia da
classe FileStream que configura o ambiente para criar um arquivo chamado dados.txt. em seguida os
objetos w e r são buffers (arquivos temporários) que permitem gravar os dados no disco. Observe que
os dados serão gravados em formato Binário.
StreamReader, StreamWriter – Classes que manipulam arquivos não binários, utilizando uma
codificação para converter caracteres para bytes ou vice versa.
A codificação das classes acima é do tipo UTF-8 que converte os caracteres corretamente e certifica
que o sistema operacional tem suporte a eles. É possível definir uma codificação diferente no
parâmetro da classe.
Exemplo :
Dim sr As StreamReader
' Abre o arquivo a ser lido.
Sr = File.OpenText("c:\MeuArquivo.txt")
' Lê cada linha do arquivo.
' Quando chegar o final do arquivo é retornado o valor "-1".
Dim x As String
While sr.Peek <> -1
x = sr.ReadLine()
Console.WriteLine(x)
End While
' Informa ao usuário que a operação terminou e fecha o arquivo.
Console.WriteLine("Final de arquivo.")
sr.Close()
O VB .NET inclue funções de versões anteriores como parte de suas bibliotecas. Essas funções são
utilizadas para acessar os dados dos arquivos, dependendo do tipo de dados é necessário usar um tipo
de acesso conforme abaixo :
• Acesso Seqüencial – Grava e lê dados do tipo texto em um bloco contínuo. Qualquer arquivo
de texto é um arquivo seqüencial.
• Acesso Randômico – Grava e lê dados do tipo texto e binário em estruturas de registros. Para
criar arquivos Randômicos são utilizados tipos de dados compostos para gerar registros com
diversos tipos de dados diferentes que são gravados como campos.
• Acesso Binário – Grava e lê dados com estruturas e formatos diversos.
130
Os arquivos de texto são geralmente abertos pelo modo seqüencial com a função FileOpen, aliás a
Microsoft recomenda utilizar a classe System.IO para tal finalidade. Antes porém deve ser
especificado o modo como os caracteres devem ser manipulados. Exemplo :
OpenMode.Input – deve ser usado se o arquivo já existe, caso contrário gera um erro.
OpenMode.Output – deve ser usado se o arquivo não existe, pois este método cria um novo
arquivo.
OpenMode.Append – deve ser usado se o arquivo não existe, pois este método cria um novo
arquivo.
Além disso é obrigatório informar um número (canal) livre para que o sistema operacional possa
manipular o arquivo, geralmente a forma correta é sempre utilizar a função FreeFile que seleciona o
canal livre automaticamente. Finalmente após utilizar o arquivo é necessário fechá-lo com a função
FileClose (NrCanal).
Para editar um arquivo já aberto é preciso ler o arquivo e atribuir seu conteúdo a variáveis, em
seguida alterar o seu conteúdo e retornar o valor dessas variáveis ao arquivo original. Há 3 funções
que copiam o conteúdo de um arquivo de texto para variáveis :
LineInput – Essa função lê uma linha inteira de um arquivo e reconhece o final da linha
automaticamente quando encontra a seqüência de Carriage Return (chr(13) - Tecla Enter) ou (chr(13)
+ chr(10)). Essa função não inclui essas seqüências no conteúdo para a variável.
InputString – Essa função permite que seja determinado um número de caracteres a serem lidos e
atribuídos a variável. Essa função deve ser usado somente nos modos Input ou Binary.
Input – Essa função lê os dados strings e números de um arquivo até encontrar caracteres
delimitadores tais como vírgula, espaço e etc. Tais caracteres delimitadores finalizam a execução da
função.
CanalVazio = FreeFile( )
FileOpen(CanalVazio, "ArquivoTeste", OpenMode.Input) ' Abre o arquivo
While Not EOF(1) ' Loop até o final do arquivo.
LinhaDoTexto = LineInput(CanalVazio) ' Lê a linha e joga para a variável.
Debug.WriteLine(LinhaDoTexto) ' Exibe o conteúdo na janela Output do IDE.
End While
FileClose(CanalVazio) ' Fecha o arquivo.
A função LineInput lê um caracter por vez até encontrar a seqüência de Return do final de linha. Essa
seqüência não é incluída no conteúdo da variável. No exemplo acima o número de arquivo
disponível foi determinado pela função FreeFile, em seguida a linha de texto encontrada foi
atribuída a variável LinhaDoTexto.
Se for necessário incluir a seqüência de Return à variável, será necessário adicionar o código :
131
Dim umCaracter As Char
Dim CanalVazio as integer
CanalVazio = FreeFile ( )
FileOpen(CanalVazio, "MEUARQUIVO.TXT", OpenMode.Input) ' Abre o arquivo.
While Not EOF(1) ‘Loop até o final do arquivo.
umCaracter = (InputString(CanalVazio, 1)) ' Lê apenas 1 caracter.
System.Console.Out.WriteLine(umCaracter) ' Imprime na janela Output do IDE.
End While
FileClose(CanalVazio)
O exemplo acima abre um arquivo no modo Input e utiliza a função InputString para ler apenas um
caracter da linha do texto, note que essa função inclui qualquer caracter da linha, tais como Return,
espaços, linhas em branco e etc.
Dim s As String
Dim i As Integer
FileOpen(1, "c:/meu.txt", OpenMode.Input)
Input(1, s)
Debug.WriteLine(s)
Input(1, i)
Debug.WriteLine(i)
FileClose(1)
O exemplo acima cria um arquivo de texto qualquer e cria duas colunas contendo os dados “Olá” e
14. Observe que os dados são separadas por vírgula incluído pela função Write, que é um delimitador
de coluna específicos para a função Input.
Para adicionar dados para um arquivo existente será necessário utilizar essas funções :
Print – Permite gravar dados formatados para um arquivo seqüencial; permite incluir um número
específico de espaços entre os caracteres o argumento SPC (n) (n – número de espaços) e incluir um
número específico de tabulação utilizando o argumento TAB (n) (n – número de tabulações).
Entretanto não inclui o caracter de início de linha (linefeed).
PrintLine – Semelhante a função Print mas inclui automaticamente o caracter LineFeed no final de
cada linha.
Write – Permite gravar dados formatados para um arquivo seqüencial separando os itens com
vírgula e incluindo aspas entre os caracteres automaticamente.
WriteLine – Semelhante a função Write mas inclui automaticamente o caracter LineFeed no final de
cada linha.
132
PrintLine(1, "Olá", " ", "Mundo") ' Separa duas strings por espaço.
PrintLine(1, SPC(5), "5 medidas de espaçamento ") ' Grava string com 5 medidas de espaço após o
‘ início do texto
PrintLine(1, TAB(10), "Olá") ' Grava uma palavra na coluna 10.
' Datas e valores booleanos são traduzidos automaticamente usando as configurações locais do
computador
PrintLine(1, aBool, " Valor Booleano")
PrintLine(1, aDate, " Data")
FileClose(1) ' Fecha o arquivo.
O arquivo lixo.txt terá o seguinte conteúdo quando aberto por qualquer editor de texto simples, como
por exemplo o bloco de notas :
Texto qualquer.
Zona 1 Zona 2
Olá Mundo
5 medidas de espaçamento
Olá
False Valor Booleano
12/2/1969 Data
' Datas e valores booleanos são traduzidos automaticamente usando as configurações locais do
computador
WriteLine(1, aBool, " Valor Booleano")
WriteLine(1, aDate, " Data")
FileClose(1) ' Fecha o arquivo.
O arquivo Lixo2.txt terá o seguinte conteúdo quando aberto por um editor de texto simples :
133
"Texto qualquer.",
"Zona 1",,"Zona 2"
"Olá"," ","Mundo"
"5 medidas de espaçamento "
,"Olá"
#FALSE#," Valor Booleano"
#1969-02-12#," Data"
Observe que as funções Write e WriteLine gravam dados booleanos e datas com os caracteres #;
todos os strings são gravados com aspas e além disso as datas são sempre gravadas no formato
universal Ano/Dia/Mês. Os números decimais devem ser informados utilizando o separador decimal
ponto (.).
Os dados strings de arquivos aleatórios podem possuir tamanhos pré-definidos que podem ser
estruturados utilizando o atributo VBFixedString da plataforma .NET. Se o tamanho dos dados
originais forem menores que os dados compostos recém criados, então o VB preenche os vazios com
espaços caso contrário os registros serão truncados.
Structure DadosPessoais
Public ID As Integer
Public Salário As Decimal
Public ÚltimaRevisão As Long
<VBFixedString(15)> Public PrimeiroNome As String
<VBFixedString(15)> Public ÚltimoNome As String
<VBFixedString(15)> Public Cargo As String
<VBFixedString(150)> Public Observações As String
End Structure
A estrutura de um arquivo aleatório é semelhante a figura abaixo, onde os dados são gravados de
acordo com a estrutura especificada, assim no exemplo abaixo o campo1 “Nome” possui o tipo de
dados string com 6 posições enquanto que o campo2 “Sobrenome” é do tipo string com 7 posições.
A largura total do registro é igual ao Campo1 + Campo2 ou seja 13 posições.
134
Para abrir um arquivo do tipo randômico, é necessário utilizar a função FileOPen com um
argumento que indica a largura de cada registro do arquivo. O tamanho de registro máximo é
32.767 bytes. Exemplo :
Structure Pessoa
<VBFixedString(30)> Dim Nome As String
Dim ID As Integer
End Structure
A forma mais correta de determinar o tamanho de uma estrutura é utilizar a função Len que retorna o
total de caracteres de uma estrutura. Exemplo :
Para editar um arquivo aleatório é preciso ler os registro para uma variável em seguida altere os
valores dessas variáveis e finalmente grave os novos dados no arquivo. O método FileGetObject
deve ser usado para ler os registros do arquivo para uma estrutura de variáveis, há várias funções
para esta finalidade porém a Microsoft recomenda utilizar FileGetObject para evitar erros de
compilação quando eventualmente salvar algum registro do tipo Object para o arquivo. Exemplo :
Dim c As String
FileSystem.FileOpen(1, "teste.txt", OpenMode.Random)
FileSystem.FilePutObject(1, "ABCDEF")
FileSystem.Seek(1, 1)
FileSystem.FileGetObject(1, c)
System.Console.WriteLine(c)
FileSystem.FileClose(1)
O exemplo acima cria um arquivo aleatório com a extensão (*.txt), observe que os dados string não
podem ser acessíveis a leitura humana, assim se o arquivo for aberto pelo Bloco de Notas os dados
serão os seguintes :
ⱯⱯⱯ
Ao passo que o método FilePutObject converte os dados lidos no arquivo para um formato
condizente para leitura. Além disso o método FileGetObject pode utilizar várias sintaxes como por
exemplo :
135
A função Seek retorna a posição atual de um cursor (leitura ou gravação) em um arquivo aleatório ou
define a posição de um cursor (leitura ou gravação) em um arquivo aleatório.
Structure Registro
Dim Nome As String
Dim ID As Integer
End Structure
Structure Registro
<VBFixedString(30)> Dim Nome As String
Dim ID As Integer
End Structure
NrArquivo = FreeFile()
TamanhoRegistro = Len(Pessoa)
FileOpen(NrArquivo, "C:/Pessoa.txt", OpenMode.Random, OpenAccess.ReadWrite, ,
TamanhoRegistro)
Pessoa.ID = 1
Pessoa.Nome = "Luiz"
FilePut(NrArquivo, Pessoa, 1)
Pessoa.ID = 2
Pessoa.Nome = "Antonio Carlos"
136
FilePut(NrArquivo, Pessoa, 2)
Seek(NrArquivo, 2)
FileGet(NrArquivo, Pessoa, 2)
MsgBox(Pessoa.ID & " " & Pessoa.Nome)
FileClose(NrArquivo)
End Sub
Conforme mostrado no exemplo acima, é possível utilizar funções como FilePut e FileGet da mesma
forma que FilePutObject e FileGetObject.
Os arquivos de acesso Binário são normalmente arquivos de pequeno tamanho pois não necessitam
de variáveis com tamanhos pré-fixados, além disso esse tipo de arquivo não pode ser lido
aleatoriamente pois não há como saber a posição específica do início ou fim de registros.
Para abrir um arquivo de acesso binário utilize a função FileOPen com o parâmetro
OpenMode.Binary, além disso não informe o número (largura) dos registros.
Exemplo :
Structure Registro
Dim Nome As String
Dim ID As Integer
End Structure
NrArquivo = FreeFile()
TamanhoRegistro = Len(Pessoa)
FileOpen(NrArquivo, "C:/Pessoa.txt", OpenMode.Binary)
Pessoa.ID = 1
Pessoa.Nome = "Luiz"
FilePut(NrArquivo, Pessoa)
Pessoa.ID = 2
Pessoa.Nome = "Antonio Carlos"
FilePut(NrArquivo, Pessoa)
Seek(NrArquivo, 2)
FileGet(NrArquivo, Pessoa,2)
MsgBox(Pessoa.ID & " " & Pessoa.Nome)
FileClose(NrArquivo)
End Sub
137
O exemplo acima utiliza o mesmo código do exemplo anterior, observe que na estrutura Registro foi
eliminado o parâmetro <vbFixedString> pois não é mais necessário, além disso as função FilePut
não utilize o parâmetro PosiçãoRegistro. A vantagem é que o arquivo final gravado no disco possui
um tamanho menor em comparação ao mesmo arquivo com acesso aleatório do exemplo anterior.
Outro exemplo :
NrArquivo = FreeFile()
For i = 1 To 10
FileGet(NrArquivo, pixel, i)
pixels = pixels & pixel
Next i
FileClose(NrArquivo)
MsgBox(pixels)
End Sub
O exemplo acima abre um arquivo de imagem e retorna os bytes recolhidos pela função FileGet e
exibe um aviso na tela.
Conclusão
• As funções de acesso seqüencial (Input, Output e Append) devem ser utilizados para ler e
gravar arquivos de texto; logs de erros ou relatórios.
• AS funções de acesso aleatório (Random) devem ser usados para ler e gravar dados para um
arquivo sem fechá-lo, além de buscar informações rapidamente.
• As funções de acesso binário (Binary) devem ser usados para ler e gravar bytes em qualquer
posição de um arquivo, como por exemplo salvar ou exibir arquivos bitmap.
Objeto Descrição
FileSystemObject Permite criar, apagar, obter informações e manipular drivers, pastas,
arquivos.
Drive Permite obter informações sobre um drive do sistema, tal como um disco
rígido, um CD-Rom, um disco RAM ou um drive de rede LAN.
Folder Permite criar, apagar, mover pastas como outras informações importantes.
File Permite criar, apagar ou mover arquivos assim como outras informações
importantes.
TextStream Permite ler e gravar arquivos de texto.
Para utilizar os serviços do FSO basta fazer uma referência a biblioteca de Scripting no projeto VB
.NET conforme os passos abaixo :
1. Clique no menu do IDE : Project > Add Reference e escolha a aba COM.
2. Selecione da lista de componentes a opção Microsoft Scripting Runtime.
3. Crie o objeto FSO : Dim meu as New Scripting.FileSystemObject
4. Ou crie o objeto FSO : meu = CreateObject (“Scripting.FileSystemObject”)
O item 3 só pode ser utilizado em projetos VB e o item 4 pode ser utilizado em projetos VB e
VBScript. A janela Object Browser do IDE exibe o nome da biblioteca, além de suas propriedades,
métodos e coleções. NO exemplo acima Scripting refere-se ao nome da biblioteca e
FileSystemObject refere-se a um objeto dessa biblioteca.
Tarefa C omando
Cria um novo objeto CreateFolder ou CreateTextFile
Apagar um arquivo ou pasta DeleteFile ou File.Delete; DeleteFolder ou
Folder.Delete
Copiar um objeto CopyFile ou File.Copy; CopyFolder ou
Folder.Copy
Mover um objeto MoveFile ou File.Move; MoveFolder ou
Folder.Move
Acessar um drive, pasta ou arquivo GetDrive, GetFolder, ou GetFile
Há alguns comandos com a mesma finalidade, como por exemplo para copiar um arquivo utilize o
método CopyFile do objeto FileSystemObject ou utilize o método Copy do objeto File. Segundo a
Microsoft, a razão de ter incluído esses comandos para a mesma tarefa, é de oferecer maior
flexibilidade de programação.
O objeto Drive obtém informações sobre vários drives do sistema, através das seguintes propriedades
:
Propriedade Descrição
TotalSize Tamanho do Drive em bytes.
139
AvailableSpace, FreeSpace Espaço disponível no drive em bytes.
DriveLetter Letra atribuída ao drive.
DriveType Tipo (removível, Fixo,Rece, CD-ROM, ou disco
RAM )
SerialNumber Número serial do Drive
FileSystem Tipo do sistema de arquivos (FAT, FAT32, ou
NTFS)
IsReady Verifica se o drive está disponível para uso.
ShareName, VolumeName Nome do compartilhamento e/ou volume
Path, RootFolder Caminho, ou pasta raíz do drive
As propriedades Path (App.Path), ChDrive e ChDir statements, e função CurDir podem retornar um
valor conhecido como Universal Naming Convention (UNC) (Convenção de nome Universal)
(semelhante à \\Server\Share…) ao invés do caminho padrão (tal como e:\Folder), dependendo de
como se executa o aplicativo ou projeto :
Método Tarefa
FileSystemObject.CreateFolder Cria uma pasta
Folder.Delete ou Apaga uma pasta
FileSystemObject.DeleteFolder
Folder.Move ou Move uma pasta
FileSystemObject.MoveFolder
Folder.Copy ou Copia uma pasta
FileSystemObject.CopyFolder
Folder.Name Retorna o nome de uma pasta
FileSystemObject.FolderExists Verifica se uma pasta existe no drive.
FileSystemObject.GetFolder Manipula uma cópia de um objeto Folder
existente..
FileSystemObject.GetParentFolderName procura o nome de subpastas..
FileSystemObject.GetSpecialFolder Procuta o caminho de uma pasta do sistema..
Método Tarefa
CreateTextFile, OpenTextFile, ou Cria um arquivo de texto sequêncial
OpenAsTextStream
Write ou WriteLine Adiciona dados ao texto
Read, ReadLine, ou ReadAll Lê dados de um arquivo de texto
File.Move ou MoveFile Move um arquivo
File.Copy ou CopyFile Copia um arquivo
File.Delete ou DeleteFile Apaga um arquivo
140
Exemplo :
Todo aplicativo que possui manipulador de erros pode detectar e corrigir automaticamente eventuais
erros que ocorrerem na execução do programa. Assim quando um erro é detectado o compilador
executa um bloco de código especializado para corrigir o problema enquanto o aplicativo está em
execução.
Um manipulador de exceções deve ser utilizado quando um método invoca um objeto ou operador
que potencialmente pode gerar uma exceção (erro). Quando uma exceção é provocada por um
método ou objeto que não possui um manipulador de erros apropriado, essa exceção é propagada
para o método chamador, isto é o método anterior, se esta rotina também não possui um manipulador
apropriado, a exceção continua sua procura de um manipulador de erros apropriado até chegar na
Memória (Pilha) quando emite uma mensagem de erro e o programa é finalizado.
Para criar um manipulador de erros estruturado utilize a estrutura Try ... Catch ... Finally conforme
abaixo :
Try
141
' Inicia um manipulador estruturado de exceções.
' Dentro desse bloco deve estar o código que
' potencialmente pode gerar uma exceção.
Catch [Filtros opcionais]
' O código dentro desse bloco é executado automaticamente se os comandos
' provocarem algum tipo de exceção e o filtro for avaliado como True.
[Blocos Catch adicionais]
Finally
' O código dentro desse bloco sempre será executado imediatamente
' antes do término do bloco Try … Catch … Finally.
End Try
O código dentro do bloco Try deverá monitorar qualquer erro causado por objetos, métodos e etc.
Quando ocorre um erro dentro desse bloco, o compilador do VB procura o comando Catch dentro da
estrutura e executa o código para manipular o erro.
Se o comando Catch não for implementado dentro desse bloco, o compilador procura o comando
Catch imediatamente fora desse bloco onde ocorreu o erro. Esse processo continua até que toda a
pilha (memória) seja examinada a procura do comando Catch, até que uma mensagem de erro seja
exibida e o aplicativo encerrado.
O código dentro da seção Finally é sempre executado em último lugar antes do controle do fluxo sair
da estrutura Try ... Catch ... Finally, mesmo que o código de Catch tenha sido executado. Assim é
necessário incluir rotinas de limpeza nessa seção, tais como fechar arquivos, liberar objetos da
memória e etc.
Try
' código que pode ocasionar o erro.
Catch e as Classe
' código que resolve o problema.
Finally
' código que faz a limpeza geral
End Try
Se ocorrer o erro da classe específica então o código dentro de Catch é executado até que o controle é
passado para o bloco Finally.
2. O erro é filtrado com base em qualquer condição, como por exemplo testar um número
de erro específico :
Try
' código que pode ocasionar o erro.
Catch When ErrNum = 5 'Type mismatch.
' código que resolve o problema.
Finally
' código que faz a limpeza geral
End Try
142
Se ocorrer o número do erro especificado no filtro então o código dentro de Catch é executado até
que o controle seja passa para o bloco Finally.
Return Strings
End Function
O exemplo acima utiliza a classe IO.StreamReader da plataforma .NET para abrir um arquivo de
texto e colocar seu conteúdo em uma coleção. Quando uma exceção de final de arquivo é encontrado
o controle do sistema é automaticamente reposicionado para o primeiro bloco Catch. Se qualquer
outro erro da classe for acionado, então o controle do sistema é reposicionado para o segundo bloco
Catch.
Observe que não importa a ação tomada pelo bloco Catch, o bloco Finally será executado
normalmente. Além disso se a exceção for diferente das classes IOException e
EndOfStreamException, o controle do sistema vai propagar o erro para o código chamador, que
possivelmente não tem um manipulador de erro disponível.
Todo o código dentro de um manipulador estruturado de exceções deve utilizar uma cópia da classe
Exception, diferentemente de um manipulador não estruturado de exceções que não a utiliza. Toda
vez que uma exceção é provocada, o objeto Err é preenchido e uma cópia da classe Exception é
criado automaticamente pelo VB .NET.
A classe Exception possui propriedades que informam a localização, o tipo e a causa do erro, tais
como : a propriedade StackTrace lista os métodos que causaram o erro; a propriedade Message é
uma mensagem de texto que descreve o erro; a propriedade HelpLink configura um link a um
arquivo de ajuda disponível; a propriedade Source contém o nome do objeto que causou o erro.
143
Um manipulador não estruturado de exceções utiliza o comando On Erro no início de um bloco de
código que trata qualquer tipo de erro que ocorrer neste bloco. Quando uma exceção é causada
dentro desse bloco, o VB desvia o fluxo do programa para uma região identificada por um número de
linha ou por um identificador com dois pontos onde deverá haver um código que trata do erro em
questão.
Esse tipo de manipulador de evento diminui o desempenho do aplicativo além de criar um código de
difícil manutenção.
Exemplo :
Sub TestarSub
On Error GoTo TratarErro
' código que potencialmente pode gerar um erro.
Exit Sub
TratarErro:
' código que manipula erros.
Resume
End Sub
No exemplo acima o código utiliza a sintaxe do comando On Error direcionando para um alinha
denominada TratarErro. A sintaxe completa é On Error Goto Linha onde linha é um argumento
que identifica a localização do manipulador de exceções.
Além disso é imprescindível utilizar o comando Exit Sub antes do bloco manipulador de erros para
interromper o fluxo do sistema, caso contrário o compilador executa todo o código do manipulador
de exceções mesmo que não haja exceções.
O comando On Error Resume Next desvia o fluxo do programa para o comando imediatamente
posterior ao comando que causou o erro, ao invés de desviar o fluxo do programa para outra
localidade no procedimento.
O comando Resume também é utilizado para desviar o fluxo do programa, entretanto o controle vai
diretamente para a linha que causou o erro. Use Resume após o código de tratamento corrigir o erro.
O comando Resume Line é uma variação de Resume que transfere o fluxo do programa para o local
definido em Line, observe porém que Resume Line deve ser utilizado somente dentro do
manipulador de erros.
O comando Resume Next também desvia o fluxo do programa para o comando imediatamente
posterior ao comando que causou o erro, porém deve ser usado somente quando o erro em questão
não interrompe a execução do aplicativo.
O comando On Error GoTo 0 desliga qualquer manipulador de erro no procedimento. Observe que
(zero) não é um identificador de linha, portanto o fluxo do sistema não é desviado para a linha zero
do código.
144
Sub TesteErro ()
' Declaração de variáveis
Dim x As Integer, y As Integer, z As Integer
' O manipulador de exceções é chamado de “DivisãoPorZero”.
On Error GoTo DivisãoPorZero
' Parte do código que pode causar um erro..
x=2
y=0
z=x\y
End Sub
No exemplo acima, o manipulador de erros foi desenhado somente para interceptar qualquer divisão
por zero, assim o manipulador de erros é desligado quando o compilador executa a divisão x por y e
não ocorre exceções. Qualquer outra exceção exibe a mensagem de erro e finaliza a execução do
programa.
145
3 – Visão Geral da Tecnologia .NET Framework
A infraestrutura .NET é um enorme ambiente de programação que possui milhares de classes
divididas em EspaçosNomeados (NameSpaces), além de novo arquivo run-time conhecido como
Common Language RunTime (CLR) que é o mecanismo que controla o sistema inteiro. O CLR
cuida dos detalhes de baixo nível de programação tais como gerenciamento de memória, processos
de comunicação e deixa o desenvolvedor basicamente com as tarefas específicas do seu aplicativo.
O CLR também permite trabalhar com diversas linguagens de programação (VB, VC++, VC#,
COBOL, etc) além de resolver o problema de compatibilidade entre DLLS, coisa que era difícil de
realizar com a antiga tecnologia COM.
Além disso a infraestrutura possui novos serviços de acesso a dados tais como ADO.net; ASP.net e
XML; conta também com nova tecnologia de criação de janelas para aplicativos conhecido como
Windows Forms e Web Forms.
A tecnologia .NET introduz o conceito de Assemblies que são arquivos do tipo DLL, mas com outras
funcionalidades extras. Agora os arquivos do tipo DLL possuem recursos extras, essas classes NET
são assemblies que podem ser inseridos no projeto com o comando Imports, portanto um assemblie é
um catálogo dos recursos existentes no aplicativo. Esse catálogo é conhecido como Manifest ou
Metadados que guardam informações críticas de um aplicativo tais como visibilidade, tipos, versões
e segurança.
O coração da infraestrutura .NET está no novo mecanismo para carregar e executar programas e
gerenciar os recursos. Este mecanismo é baseado em uma nova regra para criar componentes
chamada de Common Language Infraestructure (CLI) criado pela Microsoft e que agora está sob
a responsabilidade e controle da organização mundial de padrões ECMA.
De agora em diante essa regra CLI especifica como o ambiente de execução de um software deve se
comportar :
• Os softwares devem trocar dados entre si sem importar com a linguagem de programação que
foram criados.
• O software deve ser executado em diferentes sistemas operacionais e em diferentes tipos de
máquinas sem a necessidade de recompilar o código fonte (a compilação em baixo-nível
ainda ocorrerá na plataforma onde for instalado o aplicativo.)
O CLI é mais uma especificação (regra geral) para criar componentes e especifica como o código
executável de um programa deve ser carregado, executado e gerenciado. Essa especificação melhora
o antigo modelo Component Object Model (COM) criado em 1992 pela Microsoft que era utilizado
para criar softwares para o Windows de versões antigas.
Esse antigo mecanismo COM permitia que os desenvolvedores Visual Basic criassem arquivos do
tipo DLL e EXE que rodassem no Windows. Esses componentes DLL e EXE tinham interfaces
(métodos, funções, propriedades e eventos) que eram utilizados por outros programas e
desenvolvedores de outras linguagens de programação. O problema era que ao passar um tipo de
dados de um aplicativo criado em uma linguagem para outro, os dados deveriam ser traduzidos para
o formato original do componente, caso contrário haveria um erro de execução.
146
Com a nova especificação CLI, esse problema é resolvido com a criação de um novo modo de passar
dados chamado de Common Type System (CTS) que determina como os tipos são declarados e
usados, entretanto a CLI ainda não foi criada para outros sistemas operacionais diferentes do
Windows, mas tanto a Microsoft como outros fabricantes anunciaram a intenção de criá-lo para
outros sistemas. O CTS oferece alguns recursos :
• Os tipos de dados primitivos (Integer, string, etc) são definidos em modo de execução e
portanto podem ser passados tranquilamente de um componente para outro, pois todos são
formatados da mesma maneira.
• Os tipos complexos (estruturas, classes, enumerações, etc) são construídos em modo de
execução e portanto podem ser passados de um componente para outro, pois todos são
construídos de tipos primitivos.
• Todos os tipos possuem informações extras dentro de cada um deles, assim um componente
manipulado por um objeto pode ser encontrado fora da definição desse objeto.
A Microsoft criou uma segunda especificação derivada da CLI denominada Common Language
Runtime (CLR) especialmente para a plataforma .NET Windows que não está sob o controle do
ECMA. A parte do CLR que controla o carregamento, execução e gerenciamento de aplicativos
.NET é chamado de Virtual Execution System (VES). O código executado pelo VES é chamado de
código gerenciado (managed code), assim todo o aplicativo criado pela tecnologia .NET é managed
code.
A CLI define um conjunto de bibliotecas (libraries - dll) que contém classes que desempenham
tarefas específicas, além disso a CLI determina que seja criada perfis (conjunto de bibliotecas) para
cada plataforma. As bibliotecas da CLI são:
Runtime Infrastructure Library - Essa biblioteca fornece os serviços essenciais necessários para
compilar e executar um aplicativo baseado na especificação CLI.
Base Class Library – Esta biblioteca fornece os serviços de runtime que são necessário para as
linguagens de programação, tais como o VB. Além disso os tipos de dados primitivos são definidos
nessa biblioteca.
Network Libray – Esta biblioteca oferece serviços de rede.
Reflection Library – Esta biblioteca oferece serviços tanto para examinar os tipos de dados quanto
para invocar os membros desse objeto todos em modo de execução, mesmo que estejam em modo de
compilação.
XML Library – Oferece serviços de XML.
Floating Point Library – Oferece suporte a operações e tipos de ponto flutuante.
Extended Array Library – Oferece suporte a matrizes multidimensionais.
Kernel Profile – Define as funcionalidades mínimas do sistema operacional utilizado, além disso
deve incluir as bibliotecas Base Class e Runtime Infrastructure.
Compact Profile – Inclue as funcionalidade do Kernel Profile + Network + Reflection + XML,
todos de forma compacta.
Note que a CLI não inclui algumas bibliotecas específicas da Microsoft tais como Windows Forms,
ASP.NET e ADO.NET pois todos foram criados especialmente para as plataformas Windows. Estas
classes foram criadas somente para essas implementações. Por exemplo o Windows 2000 aceita
todas as bibliotecas CLI além de bibliotecas adicionais não definidas pela CLI.
1 – NameSpaces
147
NameSpaces (EspaçoNomeado) são similares a pastas que agrupam várias classes com métodos,
funções e propriedades diferentes. Dentro de um NameSpace não é permitido incluir dois métodos
com o mesmo nome, ou duas classes com o mesmo nome, dessa forma não há nomes ambíguos no
mesmo espaço.
Os NameSpaces são utilizados somente para declarar uma variável objeto com um Tipo
Completamente Qualificado. Exemplo :
Nos tempos áureos do C++, os fabricantes de software criavam várias classes específicas e
colocavam à venda no mercado. Entretanto quando o consumidor instalava várias classes diferentes
no seu computador, o compilador não conseguia executar as ações pois haviam várias classes e
membros com o mesmo nome.
Então para colocar ordem nessa bagunça os comitês internacionais decidiram criar uma forma de
distribuir as várias classes em lugares nomeados, assim criou-se os NameSpaces.
2 – Módulos e Assemblies
Quando um código fonte é compilado, o compilador precisa resolver os nomes dos tipos utilizados
nesse código fonte para as definições dos tipos, se o compilador encontrar a referência no mesmo
projeto então ele cria as definições. Mas quando as referências estão fora do código fonte o
compilador precisa saber o lugar exato dessas referências para criar as definições de tipo, para isso
utiliza-se a referência aos assemblies que contém essas informações. Por exemplo pode-se compilar
na linha de comando um projeto que faz referência a uma classe (Assembly) com um tipo de dados
específico.
Quando um projeto VB .NET é criado, o sistema automaticamente faz referência a dois assemblies
(Assembly Manifest) :
148
Por default, os assemblies não são compartilhados por outros aplicativos. Assim os assemblies
podem ser instalados em um diretório simples junto com o aplicativo original, desta forma torna-se
fácil instalar e remover um aplicativo. Para instalar o aplicativo, basta criar um diretório e copiar
todos os arquivos para dentro dele. Para apagar um aplicativo basta apagar o seu diretório. O registro
do Windows não é usado para esses casos.
Agora quando um aplicativo for compartilhado por mais de um programa, ele deve ser copiado para
um diretório especial chamado de Global Assembly Cachê (GAC), que é uma área do disco
normalmente em um subdiretório do Windows que agrupa todos os assemblies compartilhados por
outros programas.
O GAC deve ser evitado o máximo possível pois somente o Windows Installer ou o programa
gacutil.exe podem manipular o GAC. Não é possível copiar e remover arquivos desse diretório.
A CLI define mais um runtime que é capaz de suportar a maioria dos recursos das linguagens
modernas de programação chamada de Common Language Specification (CLS) que é um
subconjunto dos recursos que são considerados chaves das linguagens.
Esse subconjunto foi criado porque nem todas as linguagens suportam todos os recursos do CLR,
então foi preciso considerar apenas aquilo que fosse compatível para cada linguagem. Assim um
componente escrito por uma linguagem de programação é completamente compatível com outras
linguagens devido ao código gerado em CLS.
O VB .NET gera código compatível com CLS, desta forma qualquer classe ou membros da classe
pode ser, por exemplo sobrecarregado por outra linguagem de programação.
Todos os compiladores (linguagens de programação) que utilizam o CLR devem copilar o código
fonte para uma linguagem intermediária (IL) também chamada de Common Intermediate Language
(CLI). A IL é uma linguagem de máquina criada pela Microsoft seguindo as determinações da CLI
que determina que todas os CLR devem compilar ou interpretar a IL na máquina que o CLR está
sendo executado. Se o IL é compilado/interpretado então a compilação deve acontecer de duas
formas :
NO primeiro caso cada método é compilado somente quando for necessário, assim quando o método
é compilado, o sistema chama faz várias chamadas ao mecanismo de compilação e acessa
diretamente o código compilado. O código compilado não é gravado no disco, assim quando o
procedimento é finalizado ou reiniciado, toda a compilação é reexecutada novamente. Este processo
é chamado de compilação Just-In-Time (JIT).
Note que no Sistema Operacional Windows todo o código é compilado para linaguagem nativa
e não interpretado.
149
6 – Metadata
Os Metadados são informações declarativas de um Assembly. Todo código fonte possui algumas
construções chamadas de procedurais e outras declarativas.
ObjetoQualquer.MembroQualquer = 5
O exemplo acima é procedural porque ele é compilado junto ao código executável que desempenha
uma ação em modo de execução, pois foi atribuído o valor 5 ao MembroQualquer do objeto
ObjetoQualquer.
O exemplo acima é declarativo porque ele não executa uma ação, apenas indica que o símbolo
(variável) ObjetoQualquer guarda uma referência ao objeto do tipo Classe Qualquer.
Os compiladores que utilizam CLR podem trabalhar tanto com informações Procedurais como
Declarativas criando arquivos .exe ou .dll.
Toda a linguagem de programação orientada a objeto precisa iniciar e destruir objetos, pois estes
ocupam muita memória. Quando um objeto não está sendo usado, a memória que ele ocupa é
necessária para uso de outros objetos. O processo de reconhecimento que identifica quando o objeto
não está mais sendo utilizado é chamado de lifetime management (gerenciamento de vida útil).
Na antiga tecnologia COM, quando um aplicativo utilizava um objeto, este notificava ao objeto em
questão sempre que um novo aplicativo fazia outra cópia dele. Da mesma forma, quando um cliente
que utilizava um objeto finalizava sua execução, o cliente notificava o objeto desse fato. O objeto
original mantinha sempre uma trilha de todos os aplicativos que utilizavam sua cópia, quando a
contagem de cópias era igual a zero, o objeto estava pronto para ser apagado da memória, esse
método de gerenciamento de memória era conhecido como Reference Counting (Contagem de
referências). O VB executava automaticamente esse procedimento chamando códigos de baixo
nível, e os programadores nem precisavam se preocupar com essa tarefa, entretanto esse mecanismo
causava alguns problemas
150
O atual CLR não utiliza mais o mecanismo de Reference counting, ao invés disso mantém um
ponteiro para o endereço em que a memória livre (memória Heap) começa, e a cada solicitação do
programa ele incrementa o ponteiro com o objeto necessário e posiciona no próximo endereço de
memória disponível, esse mecanismo de alocação de memória é muito rápida, este processo se repete
enquanto durar a capacidade de memória do computador e nenhuma ação é executada até que o
objeto não esteja mais sendo utilizado pelo aplicativo.
Quando não há mais recursos na memória Heap, então o gerenciador de memória inspeciona todas as
posições de memória alocadas anteriormente que podem ser liberadas examinando as variáveis do
aplicativo que faz referência aos objetos. Quando esses objetos em que as variáveis apontam
(referenciam) estão em uso, o gerenciador consegue visualizá-las através das variáveis do programa,
pois o runtime tem acesso total a todas as informações dos tipos declarados no aplicativo. Assim o
gerenciador de memória pode encontrar todas as posições da heap que estão em uso.
Durante este processo, o runtime certifica que todos os blocos de memória estão preenchidos de
forma contínua desde o início do heap, liberando os espaços remanescente para satisfazer as novas
necessidades da memória em uso quando o runtime não encontrar mais as variáveis que referenciam
o objeto alocado na memória.
Este processo de liberar memória é conhecido como Garbage Collection (GC), esse termo se aplica
a todos os métodos de gerenciamento de vida útil (lifetime management). A parte que o Garbage
Collection gerencia a memória é chamado de Garbage Collector.
Todo o aplicativo criado com a tecnologia .NET é processado através de código gerenciado. Para
criar um código gerenciado siga os passos a seguir :
Para um programador VB .NET um assembly é similar aos tradicionais arquivos. DLL ou EXE,
exceto que eles contém informações adicionais, assim como os antigos componentes COM tinham
arquivos OLB ou TLB separados chamados de Type Library (biblioteca de tipos). Quando um
aplicativo é compilado, o compilador cria automaticamente um assembly para o arquivo .EXE ou
.DLL.
O CLR lê os dados do Assembly para gerenciar memória, carregar classes, gerenciar objetos, invocar
métodos, acessar as versões e recursos dos componentes, reforçar segurança, gerar código nativo.
151