Vous êtes sur la page 1sur 151

Visual Studio.

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 :

• Visual Basic 1 – Facilitou a criação de aplicativos DESKTOP para Windows.


• Visual Basic 4 – Incluiu a nova tecnologia COM2 que permitia a criação de controles OCX,
arquivos DLL e servidores EXE para Windows.
• Visual Basic .NET – Incorpora uma nova Tecnologia denominada .NET Framework,
especialmente criada para Internet, Aplicativos Servidores, Componentes e XML.

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.

O Visual Basic é a combinação de três componentes :

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 VS vem originalmente em 4 versões Academic, Professional, Enterprise Developer e Enterprise


Architect, sendo que a última é a versão mais completa.

1.1 – Hardware necessário para instalação

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 :

Hardware Enterprise Architect Enterprise Professional Academic

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 melhor o desempenho do VS .NET desligue o antivírus na instalação; desfragmente o disco


rígido; faça um upgrade da memória.

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.

1.2 – Conceitos para o desenvolvimento de aplicativos Microsoft

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.

Para desenvolver aplicativos Windows, a Microsoft utiliza a Modelagem de Aplicativos Enterprise


(EAM - Entreprise Application Model) que envolve seis etapas :

• O Modelo de Desenvolvimento – Processo de desenvolvimento do software.


• O Modelo de Negócios – Define o objetivo do software.
• O Modelo do Usuário – Refere-se a interface, documentação, treinamento, suporte e
configuração ao usuário.
• O Modelo Lógico – Define a estrutura lógica e a modelagem dos objetos e serviços do
software.
• O Modelo Tecnológico – Define a reutilização dos componentes do software, do sistema, do
gerenciamento dos recursos.

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 modelo de desenvolvimento envolve três etapas :

• Desenho Conceitual (Conceptual Design) – Trata o sistema do ponto de vista do usuário.


• Desenho Lógico (Logical Design) – Identifica os objetos e serviços do negócio.
• Desenho Físico (Physical Design) – Implementa o desenho lógico incluindo as soluções
específicas de hardware e software.

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

Para criar o desenho lógico é preciso seguir os passos abaixo :

1. Identificar os objetos e serviços do negócio


2. Definir a interface
3. Identificar as dependências do objeto
4. Validar o desenho lógico
5. Revisar e refinar 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

A performance (desempenho) é a velocidade e a eficiência que o sistema executa as tarefas. O


desempenho tem que ser considerado pelo ponto de vista dos recursos do sistema, isto é o total de
recursos que o sistema utiliza para executar a tarefa. E do ponto de vista do usuário, isto é o tempo
gasto que o sistema utiliza para executar a tarefa.

Entretanto é necessário ter um ponto de equilíbrio entre o desempenho e outras considerações em


relação ao software, pois o código que incrementa a performance pode afetar outros aspectos do
sistema.

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.

O sistema pode centralizar todos os componentes em um único lugar de forma a substituir o


componente debilitado pelo componente corrigido. Outro caso seria dividir os componentes em
pequenos pedaços de forma a isolar o problema em áreas específicas

O ideal é dividir os componentes em pequenos pedaços de código e centralizá-los em um único


lugar, assim um sistema cliente servidor pode centralizar os pedaços dos componentes no servidor e
permitir que a manutenção seja feita no próprio servidor sem a participação do usuário no processo.

Extensibility

6
Extensibilidade é a capacidade de integrar outros aplicativos ao sistema. Para alcançar a
extensibilidade pode-se utilizar as regras abaixo :

• Dividir os serviços do sistema em pequenos componentes que possuem membros e executem


tarefas específicas que possam ser reutilizáveis por outros sistemas.
• Criar componentes COM ou .NET que podem ser sempre utilizados em outras plataformas.
• Se o sistema for WEB utilize os serviços do IIS Internet Information Service para enviar
informações ao Browser dos usuários.

Scalability

A escalabilidade é a capacidade que um sistema possui de mudar de um ambiente de pouca utilização


para um ambiente de intensa utilização do sistema sem afetar suas funcionalidades. O ambiente de
intensa utilização pode envolver :

• Aumento do número de usuários


• Aumento do tráfico do sistema na rede
• Serviços que utilizem os dados do aplicativo

Assim a escalabilidade também está ligada a performance do sistema, entretanto a escalabilidade é


mais especializada que a performance pois trata de técnicas que ajudam na melhoria do desempenho
de redes, distribuição de dados, servidores de dados, camadas de dados e etc.

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

2.0 – Arquivos gerados pelo 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.

Item do projeto Extensão Descrição


Janela .vb Janela para aplicativos Desktop.
Classe .vb Arquivo de código para classes
Modulo (Visual Basic) .vb Arquivo que agrupa funções
Component Class .vb Uma classe de componentes.
User Control .vb Controle para aplicativos
Data Form Wizard .vb (.aspx para Uma janela de dados
projetos WEB.)
DataSet .xsd Arquivo DataSet para criar esquemas XML
Arquivo XML .xml Arquivo XML
Esquema XML .xsd Arquivo para criar Esquemas de documentos XML.
Code File .vb Arquivo de código
Custom Control .vb Classe para criar controles para aplicativos Windows.
Página HTML .htm Página HTML que inclui código.
Inherited Form .vb Janela baseada em outra janela existente.
Web Custom Control .vb Classe para criar um controle servidor ASP.NET.
Inherited User Control .vb Novo controle baseado em um controle existente.
Windows Service .vb Classe para criar Serviços Windows.
COM Class .vb Classe baseada em componente COM
Transactional .vb Classe para usar componentes transacionais.
Component
Arquivo texto .txt Arquivo de texto
Frameset .htm Arquivo HTML que possui várias páginas HTML.
Arquivo XSLT .xslt Arquivo usado para transformar documentos XML
StyleSheet .css Arquivo estilo planilha para definições HTML
Installer Class .vb Classe para ser chamada em processos de instalação.
Crystal Report .rpt Um relatório Crystal Report
Arquivo Bitmap .bmp Arquivo bitmap.
Arquivo de Cursor .cur Cursor padrão
Icone .ico Ícone padrão
Arquivo Assembly .resx Arquivo usado para armazenar recursos para o aplicativo
Resource
Arquivo Assembly .vb Arquivo que contém informações do Assembly.
Information
Arquivo Application .config Arquivo usado para configurações do aplicativo.
Configuration

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.

Arquivos de um projeto WEB

Arquivos Extensão Descrição


Janela Web 2 arquivos: .aspx Uma janela WEB.
.vb
Web Service 2 arquivos: .asmx Componente que troca mensagens usando os protocolos
.vb padrões HTTP, XML, XSD, SOAP e WSDL.
Class .vb Arquivo de classe.
Modulo (Visual Basic) .vb Arquivo que agrupa funções
Component Class .vb Classe de componentes
Data Form Wizard .aspx (.vb para Uma janela de dados para aplicativos WEB.
projetos locais)
DataSet .xsd Arquivo para esquemas XML usando DAtaSet
Web User Control .ascx Controle servidor ASP.NET
Página HTML .htm Página HTML que inclui código
Frameset .htm Um pagina HTMP que inclui várias páginas HTML.
Style Sheet .css Arquivo estilo planilha usado para definições HTML
Arquivo XML .xml Arquivo XML .
Esquema XML .xsd Arquivo esquema para documentos XML.
Arquivo XSLT .xslt Arquivo usado para transformar documetnos XML
Web Custom Control .vb Controle ASP.NET server.
Arquivo de código .vb Arquivo de código
Dynamic Discovery .vsdisco Arquivo baseado em XML usado para descobrir o caminho
Document do servidor WEB.
Static Discovery .disco Arquivo de mecanismo de procura para servidores XML
WEB.
Global Application .asax Arquivo para manipular eventos ASP.NET
Class
Web Configuration .config Arquivo de configuração para aplicativos WEB
Texto .txt Arquivo de texto
Installer Class .vb Classe chamada em processos de instalação..
Crystal Report .rpt Arquivo Crystal Report
Bitmap .bmp Imagem Bitmap
Cursor .cur Cursor Padrão
Icon File .ico Ícone padrão
Assembly Resource .resx Arquivo de recursos utilizado pelo aplicativo
File
Assembly Information .vb Informações gerais do assembly
File
JScript File .js Código JScript
VBScript File .vbs Código VBScript
Windows Script Host .wsf Arquivo para Windows scripting..
9
Em versões anteriores do VB, as janelas tinham extensões .frm, os controles tinham extensões .ctr, as
classes tinham a extensão .cls.

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.

2.1 - Nova Estrutura do programa escrito em VB .Net

A nova estrutura do programa deve seguir essas etapas:


1. Utilize os comandos Option para verificar os erros de lógica e de sintaxe.
2. Utilize o comando Imports para acessar os recursos da tecnologia .NET Framework.
3. O procedimento Main ( ) será o ponto inicial do programa, ou seja o código que será
executado em primeiro lugar.
4. Utilize os comandos Class, Module ou NameSpace se for criar objetos para o programa.
5. Utilize comandos de compilação condicional #if .. #else... se necessário.
Exemplo 1 :

' Programa escrito em Visual Basic .


Option Explicit
Module Olá
Sub Main( )
MsgBox("Olá Mundo!") ' Exibe a Mensagem na tela.
End Sub
End Module

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.

Quando criamos um programa em VB escolhendo Windows Application na janela de opções, o


Visual Studio .NET cria um projeto contendo referências e uma classe chamada sempre de form1.vb.
Exemplo 2 :

Public Class Form1


Inherits System.Windows.Forms.Form
‘ O código abaixo foi criado automaticamente pelo Visual Basic
#Region " Windows Forms Designer generated code "
Public Sub New()
MyBase.New()

' This call is required by the Windows Forms Designer.


InitializeComponent()

' Add any initialization after the InitializeComponent() call.


End Sub

' Form overrides dispose to clean up the component list.


Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then

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.

2.2 – Atribuir nomes aos elementos do seu programa

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.

2.3 – Utilizando quebra de linha e combinação de código

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 :

Text1.Text = "Olá" : Vermelho = 255 : Text1.BackColor = Vermelho

2.4 – Caracteres especiais no VB .Net

Alguns caracteres possuem significados diferentes na linguagem, veja a seguir :

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!

2.5 – Criar comentários no Código

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 :

' Este é um comentário no início do código


Text1.Text = "Hi!" ' Este é um comentário na mesma linha do código

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.

2.6 – Limitações do Visual Basic .NET

As versões anteriores do VB tinham várias limitações no código, veja abaixo :

• Número de variáveis usadas no mesmo código.


• Número de funções usadas no mesmo código.
• Número de arquivos abertos no mesmo código.
• Número de janelas abertas no mesmo código.
• Dentre outras...

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.

2.7 - Compilação Condicional

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 :

#Const MeuPaís = "BRASIL"


#Const Versão = "8.0.0012"
#Const NúmeroPadrão = 36

2.7.2 – Ocultando ou expandindo o código

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 :

#Region "O código dentro de Region é ocultado clicando sobre #Region"


Private components As System.ComponentModel.Container
Dim WithEvents Form1 As System.Windows.Forms.Form

Private Sub InitializeComponent()


components = New System.ComponentModel.Container
Me.Text = "Form1"
End Sub
#End Region

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.

2.8 – Técnicas de codificação e programação

É 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.

Quando for nomear elementos, utilize as seguintes técnicas :

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.

Tipo do Controle Prefixo Exemplo


3D Panel pnl pnlGroup
ADO Data ado adoBiblio
Animated button ani aniMailBox
Check box chk chkReadOnly
Combo box, drop-down list box cbo cboEnglish
Command button cmd cmdExit
Common dialog dlg dlgFileOpen
Communications com comFax
Controles ctr ctrCurrent
Data dat datBiblio

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 :

Menu Nome do Menu


File Open mnuFileOpen
File Send Email mnuFileSendEmail
File Send Fax mnuFileSendFax
Format Character mnuFormatCharacter
Help Contents mnuHelpContents

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) :

Escopo Prefixo Exemplo

Global g gstrUserName

Module-level m mblnCalcInProgress

Local to procedure Nenhum dblVelocity

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:

gintIdadeDoAluno ‘ Variável global , do tipo de dados inteiro , Idade do aluno


(g + int + Idade Do Aluno)

mstrNomeDoAluno ‘Variável a nível de módulo, do tipo string, Nome do Aluno


(m + str + Nome Do Aluno)

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):

Tipo de Dado Prefixo Exemplo


Boolean bln blnFound
Byte byt bytRasterData

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 :

cdtCli‘Uma variável do tipo de dados composto , Cliente


( cdt + Cli)

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.

Microsoft SQL Server


• Evite o nome com abreviações, somente use abreviações quando tiver um significado
consistente.
• Quando nomear funções no SQL Server utilize a descrição do valor retornado. Exemplo :
RetorneNomeJanelaAtual( ) .
• Os nomes de arquivos, pastas, procedimentos armazenados devem descrever o seu propósito.
• Evite reutilizar nomes de funções para variáveis ou vice-versa. Exemplo : Função com nome
ProcessarArquivo( ) Variável com nome IProcessarArquivo.
• Evite utilizar homônimos ou palavras com mesmo fonema . Exemplo Rigth e Write.
• Certifique-se que não há erros quando soletrar palavras. Pois algumas palavras possuem
significados diferentes em certas regiões do Globo. Exemplo Check e Cheque não tem o
mesmo significado, Color e Colour não tem o mesmo significado.
• Evite usar marcações especiais quando nomear elementos , tais como $ , %. (utilizadas para
string e inteiros repectivamente).

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'

2.9 – Declarando Elementos

A linguagem utiliza alguns tipos de instruções tais como :

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 :

1. Comandos de declaração – Usados para nomear variáveis, constantes, matrizes, definir


procedimentos e objetos.
2. Comandos de execução – Usados para executar uma ação, e englobam todos os comandos
de loop, comandos de decisão e todos os comandos que utilizam operadores matemático ou
condicionais.

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.

Quando se declara elementos, o processo envolve as seguintes considerações :

1. Variáveis – É o espaço reservado dentro da memória do computador, para ser usado no


programa.
2. Comandos de Declaração – São comandos do VB que declaram elementos na memória.
3. Tipo de Dados – É o tipo de dados fundamental que o elemento deverá pertencer.
4. Vida útil (LifeTime) – É o período de execução que o elemento está disponível para ser
usado.
5. Escopo – É a extensão que o elemento deve atingir, sem ser declarado novamente.
6. Acessibilidade – É a forma que o código deve fazer uso do elemento.
7. Nomes Ambíguos – Quando dois elementos têm o mesmo nome, e como o VB resolve este
problema.

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.

Para usar variáveis é necessário aplicar os Comandos de Declaração, utilizando as técnicas de


codificação e programação já explicadas acima. Observe que quando se declara uma variável , o
compilador reserva um espaço na memória para o valor, mas não a cria explicitamente. Para criar
explicitamente uma variável, é preciso declarar a variável e atribuir um valor.

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 Private é um modificador de acesso e declara variáveis em todos os blocos de


código, e assim como o comando Dim, só podem ser acessadas no código que foram declaradas. E
não podem ser acessadas por outros blocos de código.

A palavra chave Public é um modificador de acesso e declara variáveis em todos os blocos de


código, e diferentemente de Dim e Private, permitem que outros códigos exteriores utilizem a
variável.

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.

Tipo de Dados Common language Tamanho em Faixa


runtime Bytes
Boolean System.Boolean 2 bytes True ou False
Byte System.Byte 1 byte 0 à 255 (não sinalizado).
Char System.Char 2 bytes 0 à 65535 (não sinalizado).
Date System.DateTime 8 bytes 0:00:00 de 1 Janeiro, 0001 à 11:59:59 da noite de 31
Dezembro, 9999.
Decimal System.Decimal 16 bytes 0 à +/-79,228,162,514,264,337,593,543,950,335 sem
virgula;
0 à +/-7.9228162514264337593543950335 com 28
dígitos depois da vírgula; o número mais próximo do
zero é

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)

O VB .NET manipula os tipos de dados elementares de duas formas :

• 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 :

Dim strTeste as string


Dim intTeste2 as System.Int32

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:

Caracter de tipo Tipo de Dado Exemplo


% Integer Dim L%
& Long Public M&
@ Decimal Const W@ = 37.5
! Single Dim Q!
23
# Double Static X#
$ String Private V$ = "Secret"

Caracter de tipo Tipo de Dado Exemplo


S Short I = 347S
I Integer J = 347I
L Long K = 347L
D Decimal H = 347D
F Single Y = 347F
R Double Z = 347R
C Char Q = "."C

4 – Vida Útil (LifeTime)


Vida útil é o período em que a variável mantém o valor na memória. Dependendo como foi declarada
a variável, sua vida útil é igual ao período de tempo que o aplicativo estiver em execução.

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.

O Escopo tem esses níveis :

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.

Ao utilizar procedimentos ou funções de Classes ou Estruturas, é obrigatório qualificar o nome além


de fazer referência à classe ou estrutura. Exemplo :

Dim DemoClass As Class1 = New Class1()


DemoClass.SomeSub( )

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.

Há duas formas de usar a técnica de ocultar elementos.

1. Shadowing através do Escopo – No penúltimo exemplo, o procedimento Perform( ) de


Mod2, ocultou o procedimento Perform( ) de Mod1, pois o compilador obedeceu a regra de
Escopo.
Outro Exemplo :

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.

Quando o procedimento Show( ) é acionado, o compilador usa a variável local declarada


dentro deste procedimento, ou seja no mesmo escopo do procedimento ativo, portanto a
variável local oculta (shadows) a variável de módulo. Portanto, no exemplo acima, para fazer
referência a variável em shadow é preciso qualificar o seu nome, como Mod3.Num em
MsgBox(CStr(Mod3.Num)).

Quando o procedimento UseModuleLevelNum( ) é acionado, o compilador usa a variável a


nível de módulo, pois não há nomes ambíguos dentro desse procedimento.

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 :

Public Class BaseCls


Public Z As Integer = 100 ' Elemento a ser ocultado (Shadowed).
End Class
Public Class DervCls
Inherits BaseCls
Public Shadows Z As String = "*" ' O Elemento para ocultar o anterior
End Class
Public Class UseClasses
Dim BObj As BaseCls = New DervCls() ' DervCls deriva de BaseCls.

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.

No caso de DObj, o elemento String ocultou (Shadowed) o elemento numérico.

2.10 – Tipos de Dados

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 :

Dim MinhaVariável as string

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 :

• IntteliSense – É um recurso que exibe as propriedades e métodos de um classe,


simultaneamente enquanto se digita no editor.
• Verificação de sintaxe – O compilador verifica a sintaxe do código escrito simultaneamente
enquanto se digita no editor.

1 – Usando tipos de dados Short

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 :

Dim MeuNúmero as short


Dim NossoNúmero as int16

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?“.

2 – Usando tipos de dados Integer

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).

A atribuição de um valor a variável é simples, utilizando apenas o operador de atribuição ( = ) e


nunca utilize separadores de milhares. Qualquer caractere diferente de número não será aceito pelo
VB, gerando erro de Type Mismatch.

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 :

VariávelInteger = “1234A” ‘Tipo Integer não suporta caracteres diferentes de número

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 :

Dim MeuInteiro as int32 ‘Mesma coisa que Integer


Dim NossoInteiro as integer

MeuInteiro = 1234
NossoInteiro = 1234

3 – Usando tipos de dados Long

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 :

Dim MeuLong As Int64

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.

4 – Usando tipos de dados Double e Single

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.

5 – Usando tipos de dados Byte

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 :

Dim MinhaFoto as Byte


MinhaFoto = recordset.Fields(“Foto”).value

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).

6 – Usando o tipo de dados Boolean

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 :

VariávelBoolean = ( “Campo” = “CAmpo”)

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.

Há duas regras para atribuição de datas :

O sinal # ativa o reconhecimento de datas no VB.

Sempre digite datas no formato mm/dd/aa para certificar-se que o sistema interpretará corretamente
os dados, em qualquer região.
Exemplo :

VariávelDate = #12/30/2002# ‘ data no formato mm/dd/aa

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).

O exemplo acima seria corretamente configurado quando transformássemos as expressões em datas,


e o resultado final seria 1 mese de diferença entre as datas. Agora o compilador interpreta exatamente
as expressões como datas, permitindo a execução de operações.

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.

O VB foi concebido em língua Inglesa/U.S. , que considera as datas no formato mm/dd/aa,


descartando qualquer possibilidade de formatação diferente, portanto trate sempre de usar essas
regras daqui para frente, de modo a evitar confusões em cálculos e atribuições.
O tipo de dados Date quando não devidamente inicializado pelo desenvolvedor, isto é não for
atribuído um valor de data, terá como valor Default 00:00:00.

8 – Usando o tipo de dados Decimal

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 :

Dim a As Decimal = 328.558


Dim b As Decimal = 12.4051
Dim c As Decimal
c=a*b
MsgBox(c)

9 – Usando o tipo de dados Object

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 :

Dim objDb As Object


Set objDb = OpenDatabase("c:\Vb5\Biblio.mdb")

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 :

Dim brush As System.Drawing.Brush


brush = New System.Drawing.Brush(bmap)
......
brush = Nothing

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.

10 – Usando o tipo de dados Char

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

11 – Usando tipos de dados String

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 :

• Os strings de tamanho variável (variable-length) que diminui ou cresce a medida que os


dados são adicionados a variável.

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 :

VariávelString = Carro ‘O VB não interpreta essa expressão como string


VariávelString = Carro Azul ‘O VB não interpreta como string, mas como uma linha de comando

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 “”.

12 – Infinity (Infinito) e outros tipos de dados

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 :

Dim dblVar As Double = 999

Dim infVar as Double


infVar = dblVar / 0

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 :

Dim var1, var2 As Double


Dim result As Double
var1 = 0
var2 = 0
result = var1 / var2
MsgBox(result)

No exemplo2, o resultado da divisão de 0 / 0 não é um número, portanto o resultado exibido em


msgbox é “NaN (Não é um Número)”. Assim como Infinity, NaN não é representado por nenhum
tipo de dados específico, mas como um recurso da linguagem.

Pode-se usar as funções IsInfinity e IsNaN para testar o resultado de cálculos matemáticos.
Exemplo:

Dim var1, var2 As Double


Dim result As Double
var1 = 0
var2 = 0
result = var1 / var2
If result.IsInfinity(result) Then
If result.IsPositiveInfinity(result) Then

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

13 – Conversões entre tipos de dados

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.

Há dois tipos de conversão no VB :


• Conversão Widening - Conversão com alargamento significa converter um valor de um tipo
de dados de pequena faixa para um tipo de dados de grande faixa de atuação. Assim pode-se
mudar de um tipo de dados integer para um tipo de dados long.
• Conversão Narrowing – Conversão com estreitamento significa converter um valor de um
tipo de dados de grande faixa para um tipo de dados de pequena faixa de atuação. Só pode
converter um tipo de dados long para integer, se o valor máximo da variável long for
suportado pelo tipo de integer, caso contrário gera erro de overflow.

Exemplo 1 de uma conversão do tipo Widening :

Dim meuLongo As Long


Dim meuInteiro As Short

meuInteiro = 32767

meuLongo = meuInteiro

MsgBox(meuLongo) ‘ retorna 32767

Exemplo 2 de conversão Narrowing :

Dim meuLongo As Long


Dim meuInteiro As Short

meuLongo = 32767

meuInteiro = meuLongo

MsgBox(meuInteiro) ‘ retorna 32767

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

Dim meuInteiro as short


Dim MeuLongo as long

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:

Dim meu as integer = 1


Dim nosso as string

Nosso = “Número “ & meu ‘além de concatenar duas variáveis


‘o operador & também funciona como conversor implícito

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

m = Val ("142 kilômetros")

MsgBox(m) ‘exibe a mensagem 142

Resumindo : O compilador do VB .NET tem duas regras default:


1. Toda variável deve ser declarada antes do uso.
2. Toda conversão do tipo Narrowing deve ser efetuada com funções de conversão
apropriada.

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.

A Microsoft recomenda sempre utilizar conversões explícitas usando as funções de conversão,


para criar um aplicativo de melhor desempenho. Além disso recomenda sempre utilizar o
comando Option Strict On.

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 :

Dim myDecimal as Decimal


myDecimal = 100000000000000000000 ' Erro de compilação.

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 é :

Dim myDecimal as Decimal


myDecimal = 100000000000000000000D ' Ok.

14 – Sistema numérico no VB .NET

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.

Decimal Octal Hexadecimal


9 &O11 &H9
15 &O17 &HF
16 &O20 &H10
20 &O24 &H14
255 &O377 &HFF

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.

2.10.1 – Estruturas de dados

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

Dim MinhaVariável as Empregado


...
MinhaVariável.Nome = “Antonio”

2.10.2 – Matrizes (Arrays)

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 :

Dim MeuArray (14) as integer ‘ Matriz de 15 elementos


Dim MeuArray (2147483646) ‘ Máximo permitido

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 :

Dim MeuArray ( ) as integer ‘ Informa ao VB alocar automaticamente os limites.

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.

As matrizes são classificadas também pela quantidade de dimensões a saber :

Matrizes Unidimensionais – Que possuem apenas uma dimensão de valores mínimo e máximo .
Como por exemplo :

Dim MeuArray (2) as string ‘Matriz unidimensional

Matrizes Multidimensionais – que possuem duas ou mais dimensões de valores mínimos ou


máximos. Como por exemplo

Dim MeuArray (2,3,4) as string ‘Matriz tridimensional


Dim MeuArray ( , , ) as string ‘também pode ser escrito dessa forma

A quantidade de combinação de elementos de um matriz (Array) multidimiensional, é o resultado do


produto dessas dimensões, assim no exemplo acima : 2 X 3 X 4 = 24 combinações de slots ou
elementos. Assim o desenvolvedor pode fazer 60 combinações de elementos possíveis na matriz
MeuArray. O VB aceita uma matriz com até 32 dimensões.

Para uma matriz multidimensional, a combinação de slots é complexo, a característica da


combinação da matriz MeuArray (2,3,4) seria a seguinte :

10 30 50 70 90 110 130 150 170 190 210 230


20 40 60 80 100 120 140 160 180 200 220 240

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.

Dim MeuArray (10, 10) as string


For i = 0 to 10
For j = 0 to 10
MeuArray ( i , j ) = “Olá “ & (i + j)
Next j
Next I
39
O Resultado final do loop será :

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.

O Vb oferece o comando ReDim para amenizar os custos de processamento e de memória de uma


matriz dinâmica, de forma que quando usado, o VB muda os limites da matriz automaticamente com
base em valores já encontrados, entretanto o comando ReDim só pode ser usado dentro de
procedimentos (procedure-level) , sem especificar o tipo de dados. Portanto, quando se cria uma
matriz com um número fixo, pode-se alterar mais tarde esse número, utilizando o comando ReDim.

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 :

Dim Matrix1() As Integer


‘ procedimento abaixo, deveria calcular os limites da matriz
‘ e em seguida dimensionar Matrix1 com ReDim:
Sub CalcValuesNow ()
.
.
.
ReDim Matrix1(19, 29)
End Sub

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:

Dim meu ( ) as string  Redim meu (1,1)  meu (1,1) = “”


Dim teu ( ) as variant  Redim teu (1,1)  teu (1,1) = Empty
Dim nosso ( ) as integer  Redim nosso (1,1)  nosso (1,1) = 0
Dim vosso ( ) as object  Redim vosso (1,1)  set vosso (1,1)= nothing

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 .

Redim Preserve Matrix1 (19 , 29)

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.

ReDim Preserve Matrix(19, UBound(Matrix, 2) + 1)

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).

ReDim Preserve Matrix(UBound(Matrix, 1) + 1, 10)

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.

Assim de forma resumida temos :

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 :

Matriz A = Matriz B ‘Considerando que Matriz B já tenha dados

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 :

Dim MinhaVariável ( ) as single ‘ Declara uma variável dinâmica com unidimensional

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

No exemplo 1, foi criado a matriz MinhaVariável e atribuído os números separadamente, enquanto


que no exemplo 2 foi criado a matriz MinhaVariável e atribuído os números simultaneamente.

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:

Dim Nossa (1,1) as Short ‘Declaração de matriz Multidimensional

Nossa (0,0) = (5) ‘Atribui os valores


Nossa (0,1) = (6)
Nossa (1.0) = (7)
Nossa (1,1) = (8)

Exemplo 5 :

Dim Nossa ( , ) as Short = New Short ( , ) {{5,6},{7,8}} “Declara e inicializa uma _


matriz multidimensional

msgbox (Nossa (0,0)) ‘ exibe o valor 5


msgbox (Nossa (0,1)) ‘ exibe o valor 6
msgbox (Nossa (1,0)) ‘ exibe o valor 7 .........

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}}

Msgbox (Tua ( 0 ) ( 0 ) ) ‘ exibe o número 5


Msgbox ( Tua (0) ( 1) ) ‘ exibe o número 6
Msgbox ( Tua ( 1) ( 0) ) ‘ exibe o número 7
Msgbox ( Tua ( 1) (1 )) ‘ exibe o número 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

Dim Número(1) as integer


Dim Letra(1) as char

Número(0) =1 : Número(1) = 2
Letra(0) = “A” : Letra(1) = “B”

Dim TudoJunto(1) as Object

TudoJunto(0) = Número
TudoJunto(1) = Letra

Msgbox (TudoJunto(0)(0)) ‘ exibe 1


Msgbox (TudoJunto(0)(1)) ‘ exibe 2
Msgbox (TudoJunto(1)(0)) ‘ exibe A
Msgbox (TudoJunto(1)(1)) ‘ exibe B

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.

2 – Matriz é um elemento da classe System.Array

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}

Msgbox (Meu.Rank) ‘ exibe o número 1 que equivale ao número de dimensões da matriz.


Msgbox (Meu.Length) ‘exibe o número 2 que equivale ao número de slots da matriz
Meu.Clear(Meu,0,1) ‘Limpa o slot 0 que contém o número 4

Msgbox (Meu(0)) ‘ exibe o número 0 como conseqüência da método Clear

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.

Resumindo : Classe é um código VB .Net estático, e Objeto é um código VB .Net em execução.


Todos os Objetos são uma cópia exata da Classe que o implementa, e cada cópia de classe não
interfere no processamento de outras cópias, isto é cada objeto tem seu próprio processamento.

Membros

Todo objeto possui Membros que são formados por :


• Propriedades – São informações armazenadas na classe.
• Métodos – São procedimentos ou ações que a classe executa.
• Eventos – São notificações que uma classe emite quando determinada ação é executada.

No VB .Net e no C++, as propriedades, Métodos e Eventos também são chamados de Membros. No


antingo VB 6 as propriedades, métodos e Eventos eram chamados de Interface. Para acessar um
44
Membro de um objeto, é obrigatório nomear o Objeto, usar um ponto e nomear o nome do Membro
desejado.
Exemplo:

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:

Dim MeuObjeto as New Class1 ( )

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

Os objetos no VB .Net estão divididos em duas fontes diferentes :


• Objetos Internos – Objetos internos, também conhecidos como intrínsecos ou (Built In), são
os objetos nativos do VB, isto é os que acompanham o ambiente de desenvolvimento VB
.Net. São objetos internos os tipos de dados elementares, tais como Integer, Long, String, etc..
Não é necessário criar referências a objetos internos antes de serem usados no aplicativo, mas
para algumas classes é necessário criar instâncias (cópias) das classes para utilizá-las.
• Objetos Externos – São todos os objetos que não acompanham o ambiente de
desenvolvimento. É obrigatório criar uma referência a estes objetos externos antes de utilizá-
los. As classes da tecnologia .NET Framework devem ser importadas usando o comando
Imports antes de serem usadas no código.

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.

Os objetos Externos e Internos permitem múltiplas ações simultaneamente. Exemplo :

Private Sub UpdateForm()


Button1.Text = "OK"
Button1.Visible = True
Button1.Top = 24
Button1.Left = 100
Button1.Enabled = True
Button1.Refresh()
End Sub

No exemplo acima, o evento UpdateForm( ) utiliza várias propriedades e métodos de um botão


simultaneamente. Entretanto a Microsoft recomenda utilizar os comandos With ... End With para
alcançar esse mesmo resultado . Exemplo :

Private Sub UpdateForm2()


45
With Button1
.Text = "OK"
.Visible = True
.Top = 24
.Left = 100
.Enabled = True
.Refresh()
End With
End Sub

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

Public Sub Som( )


Beep
End sub

O Exemplo acima cria um procedimento público Som, que pode ser acessado por outras partes do
código. Exemplo :

Dim NovaJanela as Form1

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 :

Dim minhaVariável as String = “Não sei como”

Para usar aspas na criação da string, é necessário criar uma dupla marcação de aspas. Exemplo

Dim minhaVariável as String = “Eu quero usar “”aspas”””

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 :

Dim minhaVariável as String = “Eu quero usar “”aspas”””


46
minhaVariável = “Agora não quero mais”

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”.

Métodos para manipular String

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 :

Dim aString As String = "Fale Agora"


Dim bString As String
bString = Mid(aString, 2, 3) ‘ retorna a palavra “ale”

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

Dim aString as String = “Fale Agora”

aString = String.Copy(“Fale Agora ou Cale-se”) ‘exibe o texto “Fale Agora ou Cale-se”

• Métodos Instance (Métodos em Instância) – Usa os métodos da classe fazendo a


qualificação da cópia da classe, isto é o nome da variável. Exemplo :

Dim aString as String = “Fale Agora”

aString.ToUpper ‘ retorna “FALE AGORA”

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 :

Dim Minha as string


Dim i as integer

Minha = “” ‘string vazia


Minha = Nothing ‘ string vazia

i = Minha.Length ‘Ocorre um erro de execução, pois a variável Minha recebeu Nothing

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”

resultado = String.Compare (m,n ) ‘resultado tem o valor de 1

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 :

Dim myString As String = "ABCDE"


Dim myChar As Char
myChar = myString.Chars(3) ' myChar = "D"

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.

Dim myString As String = "ABCDE"


Dim myInteger As Integer
myInteger = myString.IndexOf("D") ' myInteger = 3

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 :

Dim aString As String = "A"


Dim bString As String = "B"
Dim cString As String = "C"
Dim dString As String = "D"
Dim myString As String
' myString = "ABCD"
myString = String.Concat(aString, bString, cString, dString)

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 :

Dim spaceString As String = _


" Este texto possui espaços "
Dim oneString As String
Dim twoString As String
' Remove todos os espaços usando o método da classe String
oneString = spaceString.Trim
' Remove todos os espaços usando a função do VB
twoString = Trim(spaceString)

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("&")

MsgBox(a) ‘mostra a string “Caco”

Acima, o exemplo demonstra o uso de Trim para remover caracteres específicos na string.

Conclui-se que a tecnologia .NET Framework encapsulou todas as funções do VB em classes,


substituindo algumas e aprimorando outras, de forma a facilitar o trabalho do desenvolvedor.
Entretanto é necessário estudar as classes básicas para saber como usá-las no código, veja as
explicações no capítulo sobre o assunto.

2.13 - Constantes e Enumerações

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:

‘Option Strict Off


Public Const IdadeDoBrasil = 500
Private Const IdadeDoMatusalém = 1500

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

Public Const IdadeDoBrasil as integer = 500, IdadeDoMatusalém as integer = 1500

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.

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs)


Handles Button1.Click

Const Sim = vbYes


Const Não = vbNo

MsgBox(Sim & " e " & Não) ‘exibe “6 e 7”

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 :

Dim myDecimal as Decimal


myDecimal = 100000000000000000000 ' Ocorre um erro de execução.

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 é :

Dim myDecimal as Decimal


myDecimal = 100000000000000000000D ' Atribuição Correta.

Enumeradores

Os Enumeradores é uma forma conveniente de agrupar conjuntos de constantes relacionadas e


também associar valores com nomes. Um exemplo prático de enumeradores é, quando se declara
uma variável no Editor de Código da IDE e no final da palavra chave AS , o VB exibe a lista de
opções de tipos de objetos disponíveis.

Para usar enumeradores use o seguinte :

Private Enum MyEnum


Public Enum MyEnum
Protected Enum MyEnum
Friend Enum MyEnum
Protected Friend Enum MyEnum

Exemplo :

Public Enum Dias


Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
End Enum

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 :

Enumerações Constantes Descrição


OKOnly vbOKOnly Botão OK somente (default).
OKCancel vbOKCancel Botões OK e Cancelar.
AbortRetryIgnore vbAbortRetryIgnore Botões Anular, Repetir, and Ignorar
YesNoCancel vbYesNoCancel Botões Sim, Não, e Cancelar.
YesNo vbYesNo Botões Sim e Não.
RetryCancel vbRetryCancel Botões Repetir and Cancelar.
Critical vbCritical Ícone de mensagem crítica.
Question vbQuestion Ícone de pergunta
Exclamation vbExclamation Ícone de exclamação
Information vbInformation Ícone de informação
DefaultButton1 vbDefaultButton1 O primeiro botão é o default (default).
DefaultButton2 vbDefaultButton2 O segundo botão é o default
DefaultButton3 vbDefaultButton3 O terceiro botão é o default
ApplicationModal vbApplicationModal A janela de mensagem é modal (default).
SystemModal vbSystemModal A janela de mensagem é System modal.
MsgBoxSetForeground vbMsgBoxSetForeground Janela de mensagem de fundo
MsgBoxRight vbMsgBoxRight Alinhamento de texto a direita
MsgBoxRtlReading vbMsgBoxRtlReading Alinhamento da direita para a esquerda
(Sistema Hebreu and Arábico).
MsgBoxHelp vbMsgBoxHelp Ajuda

Exemplo :

MsgBox ("olá", MsgBoxStyle.Critical + MsgBoxStyle.OKOnly + MsgBoxStyle.SystemModal)

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

Considere as variáveis abaixo :

Dim X as integer
Dim Y as integer
Dim Z as double

Soma : X=4+3 retorna 7


Subtração : X=4–3 retorna 1
Y=–X ainda utilizando o exemplo acima – X retorna -1 (Muda o sinal)
Multiplicação : Y = 5 * 5.55 retorna 28 porque Y é Integer e arredonda números decimais
Divisão : Y =4/3 retorna 1 porque Y é Integer e arredonda números decimais
Exponenciação : Y=4^2 retorna 16
Divisão Inteira : Y = 23 \ 5 retorna 4
• A divisão inteira retorna o número de vezes que um número pode ser divido por outro, no
exemplo acima 23 pode ser dividido por 5 apenas 4 vezes. Em outras palavras, divisão inteira
retorna apenas a parte inteira da divisão.
Módulo Aritmético : Y = 5 Mod 2 retorna 1
• O módulo aritmético retorna apenas o resto da divisão entre dois inteiros.
Z = 100.3 Mod 4.13 retorna 1.18
• O módulo aritmético retorna apenas o resta da divisão em ponto flutuante se os dois divisores
forem ponto flutuante.
Divisão por Zero :
• Pode retornar NaN se for zero.
• Pode retornar +Infinito (>0)
• Pode retornar –Infinito (<0)

2. Operadores de Comparação

Esses operadores comparam duas expressões e retornam um valor Boolean como resultado.

Comparação entre números :


Igualdade ( = ) : 23 = 23 retorna True
Diferença (<>) : 23 <> 23 retorna False
Maior que (>) : 23 > 2 retorna True
Menor que (< ) : 23 < 2 retorna False
Menor ou igual (<=) 23 <= 23 retorna True
Maior ou igual (>=) 23 >= 23 retorna True

Comparação entre strings :


O compilador usa o operador Like interno para executar as comparações entre strings usando um
padrão, se o padrão for igual retorna True senão retorna False, funcionando da mesma forma que os
números. Exemplo :

“73” > “9” retorna True


53
“73” = “73” retorna True
“aaa” > “aa” retorna True

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.

O padrão de comparação é alterado pelo comando de comparação Option Compare.

Option Compare
O comando Option Compare indica ao compilador o padrão para comparar strings. O comando
possui esta sintaxe :

Option Compare Text


Option Compare Binary

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 < À < Ê < Ø < à < ê < ø

Assim, os caracteres em maiúsculos, acentuados, e outros possuem uma ordem de classificação


binária interna no VB, segundo a ordem acima.

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 :

' Muda o comportamento das comparações para Binário.


Option Compare Binary ' "AAA" é menor que "aaa".
' Muda o comportamento das comparações para Texto.
Option Compare Text ' "AAA" é igual à "aaa".

Comparação entre Objetos


Para comparar objetos é obrigatório usar o operador Is. O compilador compara os 2 objetos testando
se eles se referem a mesma cópia (instância) de um objeto.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”.

Dim x As New MyClass()


Dim y As New MyClass()
If x Is y Then
‘msgbox (“São iguais”)
end if

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.

É possível descobrir o tipo do objeto criado utilizando o operador TypeOf...Is. Exemplo :

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 :

Dim X as string = “Meu fusca “

X = X & “Amarelo” ‘atribui a string “Meu fusca Amarelo”

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 :

Dim myNumber As Integer


Dim var1 As String
Dim var2 As Integer
myNumber = 2 + 2 ' Retorna 4.
myNumber = 4257.04 + 98112 ' Retorna 102369.04.

Option Strict On
' inicializa as variáveis de diferentes tipos.
55
var1 = "34"
var2 = 6
myNumber = var1 + var2 ' Gera um erro de compilação.

Option Strict Off


Var1 = "34"
Var2 = 6
myNumber = var1 + var2
' Retorna o número 40 como resultado da soma após a
‘string Var1 ser convertida para número. O uso de
Option Strict Off não é recomendada.

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).

Os operadores lógicos são : And, Or, AndAlso, OrElse, Xor, Not.

Operações com Expressões

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.

Portanto os operadores AndAlso e OrElse economizam tempo e recursos de processamento e


também são conhecidos como operadores Short-Circuiting.

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.

• Primeiro o valor é convertido para formato binário :


3 em binário é = 011
5 em binário é = 101
• Em seguida os binários são comparados uma posição por vez. Se ambas as posições forem 1,
então 1 será o resultado da comparação dessa posição . Se uma delas for zero, então zero será
o resultado da comparação dessa posição :
011 3 em decimal
101 5 em decimal
001 O resultado em formato binário
Convertendo para o formato decimal, 001 é o formato binário do número 1, então x = 1.

57
Dim x As Integer
x = 3 or 5 ' x = 7

No exemplo acima, o compilador transforma os números em binário e executa uma comparação em


bitwise com o operador Or a seguir :

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

No exemplo acima, o compilador transforma os números em binário e executa uma comparação em


bitwise com o operador XOr a seguir :

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

No exemplo acima, o compilador transforma os número em binário e executa uma comparação em


bitwise com o operador Not, que inverte a ordem dos bits incluindo o sinal, por isso o resultado é -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

Os operadores de atribuição executam a tarefa de pegar um valor a direita do operador e atribuí-lo a


variável a esquerda do operador. Os valores de atribuição podem ser outras variáveis, expressões,
funções, entretanto todas devem obedecer as formas de conversão já estudadas.

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 :

Dim var1 As Integer = 10


Dim var2 As Integer = 3
var1 ^= var2 ' O valor de var1 é agora 1000.

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 :

Dim var1 As Integer = 10


Dim var2 As Integer = 3
var1 *= var2 ' O valor de var1 é agora 30.

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 :

Dim var1 As Integer = 12


Dim var2 As Integer = 3
var1 /= var2 ' O valor de var1 é 4.

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 :

Dim var1 As Integer = 10


Dim var2 As Integer = 3
var1 \= var2 ' O valor agora de var1 é 3.

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 :

Dim var1 As Integer = 10


Dim var2 As Integer = 3
var1 += var2 ' O valor agora da var1 é 13.

' Este exemplo usa variáveis string.


Dim var1 As String = "10"
Dim var2 As String = "3"
var1 += var2 ' O string agora da variável var1 é "103".

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 :

Dim var1 As Integer = 10

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 :

Dim var1 As String = "Hello "


Dim var2 As String = "World!"
var1 &= var2 ' A string de var1 é agora "Hello World!"

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 :

‘esse exemplo utiliza operador com uma expressão


Dim Var1 as integer = 2
Var1 += (1+2) ^ 2 ‘ o valor retornado é 11

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.

De forma clara, o operador AddressOf muda o “curso” de um procedimento qualquer para o


procedimento que foi informado a direita do operador. Exemplo :

Public Sub ButtonClickHandler(ByVal sender As Object, e As System.EventArgs)


Msgbox (“Outro evento para o botão.”) ‘Exibe a mensagem ‘Outro evento para o botão’
End Sub

Public Sub New()


AddHandler Button1.Click, AddressOf ButtonClickHandler
End Sub

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 :

Dim t As Type() = {GetType(Integer),GetType(System.Int32),GetType(String),GetType(Double())}


Dim i As Integer
For i = 0 To t.Length - 1
Console.WriteLine(t(i).Name)
Next i

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

O VB dentro de uma expressão, executa os cálculos de operadores nessa ordem :

Operadores Aritméticos e Concatenação


1. Exponenciação (^)
2. Negação (–)
3. Multiplicação e Divisão (*, /)
4. Divisão Inteira (\)
5. Módulo aritmético (Mod)
6. Adição e Subtração (+, –), Concatenação de strings (+)
7. Concatenação de strings (&)

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

Operadores Lógicos e Bitwise


1. Negação (Not)
2. Junção (And, AndAlso)
3. Disjunção (Or, OrElse, Xor)

61
É possível alterar a ordem de precedência dentro de uma expressão, utilizando parênteses entre os
membros da expressão. Exemplo :

x = ((4 +2) ^2) – (5 * 3) ‘x retorna 21


x = 4 + (2 ^ 2) - (5 * 3) ‘x retorna -7

2.15 – Procedures (Procedimentos)

Todo procedimento (procedure) é um bloco de código estruturado dentro de um comando de


declaração inicial e finalizado com um comando End. Todo o código VB é escrito em procedures é
completamente estruturado.

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).

O VB utiliza os seguintes tipos de Procedures :

• 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.

Os procedimentos podem oferecer os seguintes benefícios :

• Permite ao desenvolvedor dividir os programa em pequenas partes lógicas, além disso


permite que se faça testes separados para cada unidade muito mais facilmente do que testar o
programa inteiro.
• Pode-se utilizar procedures escritos por outras linguagens de programação, com ou sem
modificação.

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:

Sub ChamarOPerador ( ) ‘procedimento Público por default


Dim dataChamada As Date ' Stamp is local to TellOperator.
dataChamada = TimeOfDay() ' função que retorna o dia hora atual.
' Usa a classe MessageBox do espaço nomeado System.Windows.Forms
MessageBox.Show("Iniciando a chamada às " & CStr(dataChamada))
End Sub

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.

Para utilizar o procedimento ChamarOperador de um código qualquer, basta fazer referência ao


nome do procedimento finalizando com parênteses ( ). Como alternativa pode-se usar a palavra
chave Call. Exemplo :
62
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles Button1.Click

ChamarOPerador() ‘ a mesma coisa que Call ChamarOperador ( )

End Sub

No exemplo acima o procedimento sub é chamado no evento clicar de um botão de comando.

Os procedimentos de Manipulação de Eventos ou simplesmente Eventos são códigos dentro de


manipuladores de eventos que executam ações em resposta a eventos invocados pelo usuário ou pelo
próprio sistema, como por exemplo o evento clicar sobre um botão de comando como no código
acima. Os procedimentos de Eventos serão estudados no capítulo “Visual Basic e a programação
orientada a objeto”.

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.

Function Somar2e2() As Integer

Dim a As Integer = 2
Dim b As Integer = 2

Return (a + b) ‘pode-se retornar valores utilizando Somar2e2 = (a + b)

End Function

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _


Handles Button1.Click

Dim Número as integer

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.

Há duas formas de se retornar valores para o código de chamada :


• NomeDaFunção = ValorRetornado – Faz com que o controle do processamento não saia da
função até encontrar os comandos Exit Function ou End Function. Isto significa que quando o
valor da função é retornada com esse esquema, o controle não é repassado para o código
chamador até que a função encontre o comando Exit Function ou End Function.
No exemplo anterior, se o desenvolvedor utilizasse Soma2e2 = (a + b) para a função, o
controle do sistema atribuiria 4 para o evento a variável Número do evento Click, mas
voltaria a função até encontrar os comandos Exit Function ou End Function, e em seguida
retornaria ao evento Click quando exibiria a mensagem.
No exemplo abaixo é demonstrado o esquema geral para usar funções, com esse tipo de valor
retornado.

• Return – Faz com que o controle do processamento retorne imediatamente ao código


chamador. No exemplo anterior, o comando Return finaliza a função e retorna o controle
definitivamente ao evento Click. Abaixo um esquema demonstrando a forma geral de uma
função com Return.

Abaixo um exemplo de como o comando Return finaliza a execução da função instantaneamente :

Public Function Tudoum() As Integer()


Dim x(2) As Integer
x(0) = 1
x(1) = 1
x(2) = 1
Tudoum = x
64
MsgBox("Ainda passa por aqui")
End Function

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button1.Click
Dim m() As Integer
m = Tudoum()
End Sub

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.

Há duas fontes de funções no VB :

• 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 :

Function TudoUm( ) As Integer()


For I = 0 To 2 ' loop simples.
TudoUm(I) = 1 ' Erro do compilador.
Next I
Return TudoUm()
End Function

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 :

Public Function TudoUm ( ) As integer()


Dim x(2) As integer
x(0) = 1
x(1) = 1
x(2) = 1
Return x
End Function

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button1.Click
Dim m() As integer
m = TudoUm( )
End Sub

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

Os procedimentos Property são comandos que manipulam propriedades de classes, módulos ou


objetos. Para definir procedimentos Property utiliza-se os comandos Property e End Property
combinado com as palavras chaves Get e Set para determinar se as propriedades são somente leitura
ou leitura-gravação.

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

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button1.Click

Dim m As New MinhaClasse()


m.Propriedade1 = "caco"
MsgBox(m.Propriedade1)

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

Return (Número1 + Número2)

End Function

Há duas formas de passar argumentos para funções ou procedimentos :

• 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 :

Elementos variáveis (ByRef) Elementos não variáveis (ByVal)


Variáveis gerais, incluindo variáveis de objeto Constantes
Campos ou propriedades (de classes) Literais
Matrizes Enumeradores
Estruturas Expressões

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:

Public Sub Increase (ByVal A() As Long)


Dim J As Integer
For J = 0 To UBound(A)
A(J) = A(J) + 1
Next J
End Sub
' ...
Public Sub Replace(ByVal A() As Long)
Dim J As Integer
Dim K() As Long = {100, 200, 300}
A=K
For J = 0 To UBound(A)
A(J) = A(J) + 1
Next J
End Sub
' ...
Dim N() As Long = {10, 20, 30, 40}
Increase(N)
' N agora é 11, 21, 31, and 41. Porque N não foi substituído por novos valore apenas alterado
Replace(N)
' N() ainda é 11, 21, 31, and 41. Pois N foi passado por Valor
' O procedimento Replace não pode modificar a variável criando uma nova matriz a variável
'Quando Replace cria uma matriz K e atribui valores para ela, a referência a N( ) é perdida.
'Assim quando ocorrem mudanças em A ( ) somente K ( ) é afetado.

No exemplo acima, o procedimento Increase alterou os elementos da matriz (membros), enquanto


que Replace tenta alterar a própria matriz, substituindo por outra.

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.

A tabela a seguir resume toda a explicação acima :

Tipo do elemento ByVal ByRef


Tipo Valor (Contém O procedimento não pode mudar O procedimento pode mudar o valor e
somente um valor) o valor nem seus membros. seus membros.
Tipo Referência (contém O procedimento não pode mudar O procedimento pode mudar tanto a
um ponteiro para a classe a variável mas pode mudar os variável como os membros da instância
ou estrutura) membros da instância (cópia) que ele aponta)
que ele aponta)

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.

O mecanismo de passagem de parâmetros influencia no desempenho do aplicativo. A Microsoft


recomenda passar argumentos por Referência quando os valores são estruturas muito extensas, pois o
argumento ByVal precisa copiar completamente os dados para a memória. Além disso, recomenda
passar valores strings ou objetos por ByVal que não influencia no desempenho.

2. Argumentos por posição ou por nome

É 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

StudentInfo("Mary", 19, #21-Sep-1981#) ‘pode preencher todos os argumentos

StudentInfo("Mary", , #21-Sep-1981#) ‘omitir um dos argumentos

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 :

StudentInfo(Age:=19, Birth:=#21 Sep 1981#, Name:="Mary")

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 :

StudentInfo("Mary", Birth:=#21 Sep 1981#)

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.

Resumidamente, as regras para forneceder parâmetros são :

• 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.

3. Argumentos Opcionais (Optional)

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 :

Sub subname(ByVal arg1 As type1, Optional ByVal arg2 As type2 = default)

Para chamar um procedimento opcional, basta omitir o valor e incluir vírgulas na posição do
argumento. Exemplo :

Call subname(arg1, , , arg4)

Dentro de um procedimento que possui um argumento opcional, é preciso identificar se o argumento


foi omitido ou explicitamente informado pelo código chamador. Para alcançar esse objeto basta
informar um valor default para esse parâmetro. Exemplo :

Sub Notify(ByVal Company As String, Optional ByVal Office As String = "QJZ")


If Office = "QJZ" Then
Debug.WriteLine("Office não informado, notifique o usuário")
Office = "Usuário"
End If
' código qualquer para informar o usuário.
End Sub

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.

4. Parâmetros em Matriz (Array)

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 :

Sub NotasEstudantes(ByVal Nome As String, ByVal ParamArray Notas() As String)


Dim I As Integer
Msgbox ("Scores for " & Nome & ":")
' Use a função UBound o maior elemento da matriz.
For I = 0 To UBound(Notas)
Debug.WriteLine("Nota " & I & ": " & Notas(I))
Next I
End Sub

NotasEstudantes("Anne", "10", "26", "32", "15", "22", "24", "16")


NotasEstudantes("Mary", "Alto", "Baixo", "Média", "Alto")
Dim NotasJohn() As String = {"35", "Ausente", "21", "30"}
NotasEstudantes("John", NotasJohn)

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.

Para usar a palavra chave ParamArray, é necessário seguir as regras abaixo :

• 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 :

Function Factorial(ByVal N As Integer) As Integer


If N <= 1 Then .
Return 1
Else
Return Factorial(N - 1) * N
71
End If
End Function

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.

6. Sobrecarregando procedimentos (Overloading)

Sobrecarregar um procedimento ou Overloading significa utilizar um único procedimento com


vários tipos diferentes de argumentos ou versões. Já foi visto anteriormente que um procedimento
pode ser definido com vários argumentos, entretanto com a sobrecarga é possível utilizar esse mesmo
procedimento utilizando uma lista de argumentos diferentes, sem precisar criar novos procedimentos
para argumento novo.

Overloads Sub Z(ByVal X As Byte, ByVal Y As Double) ' Overload 1.


Overloads Sub Z(ByVal X As Short, ByVal Y As Single, ByVal Z as Double) ' Overload 2.
Overloads Sub Z(ByVal X As Integer, ByVal Y As Single, Byval Z as Decimal) ' Overload 3.

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 :

• Cada versão deve ter o mesmo nome do procedimento original.


• Para cada versão pelo menos um elemento dos argumentos devem ser diferentes, isto é ou o
número de argumentos devem ser diferentes, ou a ordem dos argumentos devem ser
diferentes ou os tipos de dados dos argumentos devem ser diferentes.
• Só é possível diferenciar as versões de um mesmo procedimento através da lista de
argumentos, em outras palavras não é permitido criar overloading diferenciando os
procedimentos pelo nome do argumento, ou pelo tipo de dados do valor retornado, ou pelo
tipo de acesso Public, Private, Static ou tampouco pelo modificador de argumento ByVal,
ByRef.
• É possível sobrecarregar uma função ou método quando construir uma classe da mesma
forma que sobrecarrega-se um procedimento simples.

Exemplo :

Overloads Sub Z(ByVal X As Byte, Optional ByVal Y As Double) ' Overload 1.


Overloads Sub Z(ByVal X As Short, ByVal Y As Single) ' Overload 2.

No exemplo acima, Overloading não é permitido pois somente o modificador de argumento


(Optional) é diferente entre as duas versões e conforme as regras acima, somente é permitido
Overloading quando os argumentos forem diferentes pelo tipo de dados ou pela ordem.

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)

' O procedimento anterior é equivalente as seguintes versões sobrecarregadas:


' Overloads Sub P (ByVal D As Date, ByVal C() As Char)
' Overloads Sub P (ByVal D As Date)
' Overloads Sub P (ByVal D As Date, ByVal C As Char)
' Overloads Sub P (ByVal D As Date, ByVal C1 As Char, ByVal C2 As Char)
' Pode-se prosseguir adicionando um argumento Char para cada versão sobrecarregada.

No exemplo acima, há um procedimento P definido com parâmetros D e uma matriz de Parâmetros


C. Para simplificar o procedimento, foi feito uma sobrecarga em 4 ou mais versões deste
procedimento, isto é possível porque um parâmetro é do tipo matriz de dados e outro parâmetro foi
criado sem matriz.

2.16 - Collection (Coleções)

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.

Os membros da interface de uma coleção são :

Propriedade ou método Descrição


Método Add Adiciona itens a coleção.
Propriedade Count Retorna o número de itens da coleção. Somente-leitura.
Método Item Retorna um item pelo índice ou pela chave (identificação única)
Método Remove Apaga um item da coleção pelo índice ou pela chave.

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 :

Public NomedaVariável As New Collection

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.

Para adicionar itens a uma collection utilize o método Add. Exemplo :

nomedaVariável.Add novoItem, novoItem.ID

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).

colWorkOrders.Add novoItem, novoItem.ID, after:=2

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.

Para apagar itens de uma coleção utilize o método Remove. Exemplo :

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).

Para retornar itens de uma coleção utilize o método Item. Exemplo :

Set woCurrent = colWorkOrders.Item(3)


ou
Set woCurrent = colWorkOrders.Item("W017493")

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 é :

• Um índice sempre deve ser do tipo de dados LONG


• Uma Key ou identificação deve ser sempre do tipo de dados STRING.

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 :

Set woCurrent = colWorkOrders(3)


ou
Set woCurrent = colWorkOrders("W017493")

É 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 :

Dim Meu as colWorkOrders


Meu(“W017493”).Prioridade = 3

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.

A variável Meu é apenas uma cópia de colWorkOrders já totalmente carregada na memória,


permitindo ao VB acessar os elementos dessa coleção de forma mais simples possível. Enquanto que
se acessarmos a Coleção colWorkOrders diretamente , sem intermediação da variável Meu, o VB
seria obrigado a acessar os itens dessa coleção ativando o mecanismo de leitura de tipos de dados
Object que exige muito mais processamento e memória.

O VB possui coleções pré-construídas no ambiente para uso do desenvolvedor. As coleções são


cópias da classe System.Collections da plataforma .Net Framework.

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.

2.17 - Estruturas de Controle de Fluxo

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 :

Private Sub mnuCut_Click (Index As Integer)


If Index = 0 Then
‘executa um código
ElseIf Index = 1 Then
‘executa outro código
ElseIf Index = 2 Then
‘executa outro tipo de código
Else ‘ Finaliza a estrutura de teste
‘executa o último código
End If
End Sub

Private Sub mnuCut_Click (Index As Integer)


Select Case Index
Case 0
‘executa um código
Case 1
‘executa outro código
Case 2
‘executa outro tipo de código
Case 3
‘executa outro tipo de código
Case Else ‘ Usa-se Else excepcionalmente para selecionar um valor inesperado
‘executa o código final
End Select
End Sub

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.

Public Sub Teste()


Dim x As Integer = 5
Dim y As Integer = 0
Try ' Estrutura para interceptar o erro.
x /= y ' Erro de "Divisão por zero".
Catch ex As Exception When y = 0 ' Intercepta o tipo de erro y = 0.
MsgBox(ex.toString) ' Mostra uma mensagem de erro amigável ao usuário.
Finally
Beep() ' Beep após o processamento completo.
End Try
End Sub

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.

Dim DataQualquer As Object ' Variável que recebe informações de data/hora.


Dim PróximoSéculo As Date
Try
PróximoSéculo = DateAdd("yyyy", 100, DataQualquer)
Catch DeuPau As System.ArgumentException
Msgbox (“Pelo menos um argumento tem um valor inválido”)
Catch DeuPau As ArgumentOutOfRangeException
Msgbox (“O resultado é maior que 32 de Dezembro de 9999”)
Catch DeuPau As InvalidCastException
Msgbox (“A variável DataQualquer não possui dados do tipo Data/Hora “)
Catch
Msgbox (“Ocorreu uma exceção desconhecida”)
Finally
Msgbox (“O erro foi avisado com sucesso”)
End Try

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.

As estruturas de Loop executam um bloco de código repetitivamente:

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 :

Dim Número as integer = 0


While Número > 6
Número = Número - 1
End While

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.

Loop zero ou mais vezes Loop pelo menos uma vez

Do Until condição Do
comandos comandos
Loop Loop Until condição

Exemplos :

Do While InStr(position, longstring, target)


position = InStr(position, longstring, target)_
+1
count = count + 1
Loop

For i = 0 To Screen.FontCount
Print Screen.Fonts(i)
Next

For Each MyTableDef In objDb.TableDefs()


List1.AddItem MyTableDef.Name
Next MyTableDef
78
A estrutura For ... Next, usa um contador com incrementos variados, utilizando a palavra chave Step.

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 :

For Each elemento In grupo


comandos
Next element

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.

For contador = início To final [Step incremenot]


[comandos]
[Exit For]
[comando]
Next [contador[, contador] [,...]]

Do [{While | Until} condição]


[comandos]
[Exit Do]
[comandos]
Loop

Private Function Somar ( )


[Comandos]
Exit Function
[Comandos]
End Function

Private Sub Form1_Load ( )


[Comandos]
Exit Sub
[Comandos]
End Sub

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.

O Comando Exit é usado em qualquer estrutura de controle, loop ou procedimento e permite


encerrar o código imediatamente após Exit.

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

No exemplo acima, o código em DemonstraçãoDoExit utiliza Exit em diversas estruturas aninhadas,


observe a sintaxe de Exit para cada situação.

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 :

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button1.Click

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.

Public Sub IniciarMatriz(Var1, Var2, Var3, Var4)


On Error GoTo ErrorHandler
' Código qualquer que gera um erro
Exit Sub
ErrorHandler:
' Código qualquer que intercepta o erro
Resume Next
End Sub

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.

Há dois momentos em um procedimento que manipula erros :


1. Disponibilizado (Enabled) – Todo procedimento possui um manipulador de erro
disponibilizado quando o desenvolvedor coloca o comando de desvio Goto NomeDaLinha.
Significa que o manipulador de evento está “ligado”.
2. Ativo (Active) – Quando ocorre um erro e o procedimento que trata do erro já está
processando os comandos. Portanto já ocorreu o desvio do fluxo do aplicativo e o sistema já
está processando o código que trata o erro.

Além disso o comando On Error pode ser combinado com os comandos :


• Resume Next – Faz com que a execução do código continue com o comando
imediatamente posterior ao comando que gerou o erro (é preferível do que GoTo).
• GoTo – Desvia o fluxo do programa para uma linha nomeada que contém o código
que trata o erro.
• GoTo 0 – Desliga o manipulador de erro para esse procedimento.
• Goto 1 - Desliga as exceções para esse procedimento.

On Error Goto ErrorHandler ' Disponibiliza a rotina de erro do procedimento


On Error Goto 0 ' Desliga a interceptação de erro.
On Error Resume Next ' Continua com os comandos após o erro.

Comando End : Finaliza imediatamente a execução do aplicativo.

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

Index – É o número que varia de 1 até o total de elementos do segumento parâmetro.


Choice – É uma matriz de parâmetros separados por vírgula ou uma variável de matriz
unidimensional.

Function Escolha(Ind As Integer) As String


Escolha = CStr(Choose(Ind, "Speedy", "AJato", "Virtua"))
End Function

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button1.Click

MsgBox(Escolha(2)) ‘exibe a mensagem “Ajato”

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 é :

VariávelObjeto = Switch ( <expr-1, value-1[, expr-2, value-2 … [, expr-n,value-n]]> )

Expr-1 – Expressão que se deseja avaliar


Value-1 – Valor ou expressão a ser retornada se a expressão correspondente for igual.

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.

2.18 - Visual Basic .NET e a programação orientada a objeto

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.

Uma classe deve possuir três qualidades :

1. Encapsulamento (Encapsulation) – Provém de cápsulas e significa que uma classe deve


reunir um conjunto de campos, propriedades, métodos e eventos em uma única entidade.
2. Herança (Inheritance) – Herança é a habilidade de poder utilizar uma classe qualquer para
poder construir outras classes baseadas nessa classe. A classe derivada herda todos os
campos, propriedades, métodos e eventos da classe básica, permitindo que seja implementada
outros tipos de funcionalidades na classe derivada.

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 :

• Sobrecarga de Membros (Overloaded) – É a técnica que permite utilizar um método ou


propriedade com o mesmo nome mas com parâmetros diferentes (número de parâmetros
diferentes ou parâmetros com tipos de dados diferentes).
• Substituição de membros (Overridden) - É a técnica que permite substituir uma
propriedade ou método herdado de um classe básica por outra propriedade ou método em um
classe derivada.
• Ocultação de membros (Shadowed) – É a técnica que permite substituir (ocultar)
localmente um membro por outro que esteja em um mesmo escopo. Por exemplo pode-se
declara uma propriedade que oculte um método de uma classe herdada de mesmo nome.

2.18.1 – Early bound e Late bound

O compilador do VB executa um processo chamado de ligação (Binding) quando um objeto é


atribuído a uma variável. Esse processo de ligação pode ser demorado e dispendioso para o sistema
ou pode ser rápido e econômico para o sistema dependendo de como for criado e atribuído o objeto à
variável.

Há dois tipos de binding no VB :

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.

Exemplo de um processo early 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).

Exemplo de um processo late bound :

DIM XLAPP AS OBJECT


DIM XLBOOK AS OBJECT
DIM XLSHEET AS OBJECT
XLAPP = CREATEOBJECT("EXCEL.APPLICATION")
'UMA CÓPIA LATE BIND DE UMA ARQUIVO DO EXCEL
XLBOOK = XLAPP.WORKBOOKS.ADD
UAM CÓPIA 'LATE BIND DE UMA PLANILHA DO EXCEL.
XLSHEET = XLBOOK.WORKSHEETS(1)
XLSHEET.ACTIVATE()
XLSHEET.APPLICATION.VISIBLE = TRUE ' MOSTRA O APLICATIVO
' COLOCA ALGUM TEXTO NA SEGUNDA LINHA DA PLANILHA
XLSHEET.CELLS(2, 2) = "ESTA É A COLUNA B LINHA 2"

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.

2.18.2 – Palavra chave New e liberando recursos do Sistema

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 :

Dim Button1 As System.Windows.Forms.Button()

Dim Button2 As New System.Windows.Forms.Button()

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 :

Button1 = New system.Windows.Forms.Button( )

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 plataforma .NET Framework utiliza um arquivo de runtime comum a todas as linguagens de


programação (CLR – Common Language RunTime) que por sua vez usa um sistema chamado de
Garbage Collection (coletor de lixos) que administra toda a memória de um aplicativo criado com a
tecnologia .NET.

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 :

Dim Button1 As System.Windows.Forms.Button()


Button1 = Nothing

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

2.18.3 – Trabalhando com Grupos de Objetos

Para trabalhar com grupos de objetos, simplesmente crie uma matriz com o tipo do objeto desejado.
Exemplo :

Dim x(10) As MeuObjeto ‘contém 11 elementos de x(0) até x(10)


Dim q As Integer
For q = 0 to 10
x(q) = New MeuObjeto( )
Next

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 :

Public colMeu As New Collection


' Cria um novo objeto e adiciona a coleção.
Private Sub CrieOObjeto()
Dim tempObjeto As New MeuObjeto()
colMeu.Add(tempObjeto)
End Sub

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.

2.18.4 - Obtendo informações de uma classe

É 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).

Exemplo de TypeName e TypeOf...Is :

MsgBox(TypeName(Ctrl)) ‘Exibe uma mensagem com o nome de classe de um variável Objeto

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.

Sub CheckType(ByVal InParam)


' Ambos If serão verdadeiros quando um
' Integer é passado como parâmetro.
If TypeOf InParam Is Object Then
MsgBox("InParam é um objeto")
End If
If TypeOf InParam Is Integer Then
MsgBox("InParam é um inteiro")
End If
End Sub

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.

A sintaxe da função CallByName é :

Resultado = CallByName(Objeto, NomeProcedimento, TipoChamada, Argumentos())

Onde :

Objeto – Nome do objeto que deseja executar as ações.


88
NomeProcedimento – String que representa o nome da propriedade ou método do objeto.
TipChamada – Tipo do procedimento a ser invocado e pode ser um das constantes abaixo :
• (Microsoft.VisualBasic.CallType.Method) – método
• (Microsoft.VisualBasic.CallType.Get) – ler uma propriedade
• (Microsoft.VisualBasic.CallType.Set) – atribuir uma propriedade

Exemplo da função CallByName :

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

Private Sub CallMatemática()


Dim Math As New Matemática()
Me.TextBox1.Text = CStr(CallByName(Matemática, Me.TextBox2.Text, _
Microsoft.VisualBasic.CallType.Method, TextBox1.Text))
End Sub

‘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:

Public / Private Class MinhaClasse

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

Public / Private Class MinhaClasse

End Class

Para criar campos simples na classe declare variáveis com os modificadores de acesso. Exemplo :

Imports Microsoft.Win32

Public Class MinhaClasse

Private localNome as string


Private localEndereço as string

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

Public Class MinhaClasse

Private localNome as string


Private localEndereço as string

Public Property Nome() As String


Get ' Retorna o valor da propriedade.
Return localNome
End Get
Set(ByVal Valor As String)
localNome= Valor
End Set
End Property

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

Public Class MinhaClasse

Private localNome as string


Private localEndereço as string

Public Property Nome() As String


Get ' Retorna o valor da propriedade.
Return localNome
End Get
Set(ByVal Valor As String)
localNome= Valor
End Set
End Property

Public Sub ContarPalavras( ) as integer


Dim intTotal as Integer
If localNome = “” then
Msgbox(“Não há nome algum informado”)
Else
intTotal = Len(localNome)
Msgbox( intTotal )
End if
End Sub

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

Public Class MinhaClasse

91
Private localNome as string
Private localEndereço as string

Private Sub New ( )


localNome = “”
localEndereço = “”
Msgbox (“Classe iniciada”)
End Sub

Public Property Nome() As String


Get ' Retorna o valor da propriedade.
Return localNome
End Get
Set(ByVal Valor As String)
localNome= Valor
End Set
End Property

Public Sub ContarPalavras( ) as integer


Dim intTotal as Integer
If localNome = “” then
Msgbox(“Não há nome algum informado”)
Else
intTotal = Len(localNome)
Msgbox( intTotal )
End if
End Sub

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

Public Class MinhaClasse

Private localNome as string


Private localEndereço as string

Private Sub New ( )


localNome = “”
localEndereço = “”
Msgbox (“Classe iniciada”)

92
End Sub

Public Property Nome() As String


Get ' Retorna o valor da propriedade.
Return localNome
End Get
Set(ByVal Valor As String)
localNome= Valor
End Set
End Property

Public Sub ContarPalavras( ) as integer


Dim intTotal as Integer
If localNome = “” then
Msgbox(“Não há nome algum informado”)
Else
intTotal = Len(localNome)
Msgbox( intTotal )
End if
End Sub

Protected Overrides Sub FinalizarMinhaClasse()


Msgbox (“Finalizando MinhaClasse”)
MyBase.Finalize() ' padrão criado pelo sistema.
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.

2.18.5.1 – Vida Útil de um Objeto

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.

A plataform NET utiliza um sistema chamado de reference-tracing garbage collection (Coletor de


lixo por trilha e referência) que periodicamente faz uma busca e liberação de recursos não mais
utilizados pelos objetos. Periodicamente o CLR (Common Language Run time) varre todo o sistema
e destrói os objetos que não estão mais sendo utilizados, os recursos do sistema são liberados mais
rapidamente quando o computador tem recursos limitados.

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.

2.18.5.2 – Construtor e Destrutor

Construtores e Destrutores controlam a criação e a destruição de objetos.

É possível criar um construtor com um ou vários parâmetros da mesma forma que se cria parâmetros
para procedimentos simples. Exemplo :

Sub New(ByVal sString As String)

Os construtores são frequentemente Overloaded (Sobrecarregados) conforme abaixo :

Sub New(Byval sString as String, iInt as Integer)

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 :

MyBase.New(sString) ‘Precisa ser chamado pela classe derivada


MyBase.New ‘Não precisa ser chamado pela classe derivada

Observe que a palavra chave MyBase é usada para fazer referência a classe básica.

Se um construtor possuir parâmetros o código de chamada deve passar os argumentos quando o


objeto for criado. Exemplo :

Dim objVariável as new MinhaClasse(“Rato”, 4)

O exemplo abaixo mostra o uso de Disposal e Finalize :

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

Public Sub New()


handle = ' Recurso alocado por uma API do Windows.
otherRes = New OtherResource() ' Objeto que aloca outro Recurso.
End Sub

' Libera os recursos manualmente.


Private Sub LiberarRecursos()
If Not disposed Then
CloseHandle(handle)
disposed = True
End If
End Sub

' Libera os recursos manualmente, chamando Dispose e liberando a fila de finalização.


Public Overrides Sub Dispose() Implements IDisposable.Dispose
LiberarRecursos()
otherRes.Dispose()
MyBase.Dispose() ' Se a classe básica implementa Dispose, então chama este método.
‘A chamada ao método SuppressFinalize da classe Garbage Collection (GC) é necessário
' para otimização porque isto assegura que os recursos serão devidamente liberados
GC.SuppressFinalize(Me)
End Sub

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.

Quando a classe derivada é encerrada, o método Dispose chama um procedimento qualquer


CloseHandle para liberar a variável handle em seguida finaliza a variável OtherRes. Observe que o
método Dispose da classe básica também é chamado no caso de existir algum código neste método.

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.

Abaixo o exemplo mostra uma forma comum de usar o destrutor Dispose :

Dim con As Connection, rs As RecordSet


Try
con = New Connection("string de conexão qualquer")
rs = New RecordSet(con, "MinhaTabela")
' Código para usar a conexão.
Finally
' Chame o método Dispose quando finalizar o uso do objeto criado.
If Not con Is Nothing Then
con.Dispose()
End If
If Not rs Is Nothing Then
rs.Dispose()
End If
End Try

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 :

Public Class ClasseBásica


Sub New()
MsgBox("Inicializando Sub New.")
End Sub

Protected Overrides Sub Finalize()


MsgBox("Destruindo classe com Sub Finalize.")
' Código de limpeza geral.
MyBase.Finalize()
End Sub
End Class

Public Class ClasseDerivada


Inherits ClasseBásica
Implements IDisposable ' Implementa o método Dispose da Interface IDisposable.
Private m_PropertyValue As Integer

Sub New(ByVal QualquerValor As Integer)


MyBase.New() ' Chama MyBase.New.
MsgBox("Sub New está inicializando a ClasseDerivada.")
' Qualquer Código de inicialização.
m_PropertyValue = QualquerValor
End Sub

Property ThisProperty() As Integer


Get
ThisProperty = m_PropertyValue
End Get
Set(ByVal Value As Integer)
m_PropertyValue = Value
End Set
End Property

Sub FaçaAlgumaCoisa()
' Código que faz alguma coisa.
End Sub

Protected Overrides Sub Finalize()


MsgBox("Finalizando e destruindo ClasseDerivada.")
' Código de limpeza aqui.
MyBase.Finalize()
End Sub

Overridable Sub Dispose() Implements IDisposable.Dispose


MsgBox("A ClasseDerivada está executando o método Dispose")
End Sub
End Class

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

2.18.6 – Propriedades, Campos e Métodos de uma Classe

As propriedades e Campos armazenam informações do objeto em execução. Os Campos são


variáveis públicas que a classe expões enquanto que as propriedades possuem códigos que controlam
como os dados serão atribuídos ou retornados ao cliente.

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 - Regras para criar propriedades

Para criar uma propriedade na classe é necessário obedecer as regras abaixo :

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.

Utilize explicitamente os modificadores de restrição ReadOnly e WriteOnly na implementação


das propriedades. O comando ReadOnly não permite que seja utilizado o comando Set na criação da
propriedade e aumenta a velocidade do processamento dos comandos. WriteOnly não permite que o
comando Get seja utilizado na criação da propriedade.

3 – Protegendo os métodos de uma classe

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

Public Function Adicionar1 (byVal intNúmero as integer) as Integer


Dim intResultado as Integer
intResultado = intNúmero + 1
Return intResultado
End Class

No exemplo acima o método MensagemDeBomDia exibe apenas uma caixa de mensagem. E a


função Adicionar1 retorna o número do parâmetro adicionado 1. Observe ainda que se os métodos

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.

5 – Diferenças entre propriedades e métodos

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:

MinhaClasse.Propriedade1(Índice) = 4 ‘Recebe o novo valor 4 com o sinal de atribuição =


MinhaClasse.Método1(NovoNúmero) ‘Somente recebe um novo valor no argumento NovoNúmero

No exemplo acima não é possível atribuir um novo valor para o Método1 sem que seja através do
argumento NovoNúmero.

6 – Propriedades Default (Padrão)

As propriedades padrões oferecem um meio de compactar o código omitindo o nome de uma


propriedade na criação do código. O VB .NET utiliza um valor default quando o desenvolvedor não
especifica uma valor para a propriedade. Exemplo :

TextBox = “A propriedade Default de uma caixa de texto é Text”

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á”.

Regras para criar propriedades Default :

• 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 :

Dim C As New Class2()


' As duas linhas abaixo acessar a propriedade da classe da forma convencional.
C.Prop1(0) = "Valor um" ‘Atribuição da propriedade.
MessageBox.Show(C.Prop1(0)) ' Retorno da propriedade.

' As duas linhas abaixo acessam uma propriedade Default.


C(1) = "Valor dois" ' Atribuição da propriedade.
MessageBox.Show(C(1)) ' Retorno da propriedade.

7 – Propriedade e métodos Overloaded (Sobrecarregados)


101
A Sobrecarga (Overloaded) é uma técnica que permite criar mais de um procedimento, método ou
construtor com o mesmo nome mas com argumentos diferentes. Exemplo :

Overloads Sub Display(ByVal theChar As Char)


' Código que exibe dados Char
End Sub
Overloads Sub Display(ByVal theInteger As Integer)
' Código que exibe dados Integer
End Sub
Overloads Sub Display(ByVal theDouble As Double)
' Código que exibe dados Double
End Sub

Observe que sem Overloaded seria preciso criar nomes diferentes para cada procedimento que faça a
mesma coisa.

Regras para Overloading (Sobrecarga) :

• Não é possível utilizar Overloaded modificando somente os modificadores ByVal ou ByRef.


• Não é possível utilizar Overloaded mudando somente o nome dos parâmetros.
• Não é possível utilizar Overloaded mudando somente o tipo de dados de retorno do método.

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.

8 – Propriedades e métodos Overriding (substituição)

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.

Regras para criação de Overriding :

• Utilize a palavra chave Overrides para definir uma nova implementação.


102
• Somente é possível criar Overrides (substituição) para membros que já estejam marcados
com a palavra chave Overridable na classe básica.
• Os membros overridden (substituídos) devem ter os mesmos parâmetros da classe básica.
• O membro overriden (substituído) pode chamar a implementação original da classe básica
utilizando a palavra chave Mybase antes do nome do método.

Exemplo :

Const Bonus As Decimal = 1.45


Const Taxa As Decimal = 14.75

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

MessageBox.Show("Pagamento normal é : " & _


PagamentoItem.PagarEmpregados(HorasTrabalhadas, Taxa))
MessageBox.Show("Pagamento com bônus é : " & _
BonusPagamentoItem.PagarEmpregados(HorasTrabalhadas, Taxa))
End Sub

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.

2.18.7 – Eventos e Delegar

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:

Button1_Click ‘Forma correta de criar um manipulador de evento

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.

1 – Adicionando eventos a uma classe

Para adicionar eventos a uma classe utilize o comando Event seguido pelo nome do evento e seus
parâmetros. Exemplo:

Public Event PorcentagemAlcançada(ByVal Porcentagem As Single, ByRef Cancelar As Boolean)

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.

2 – Criando manipuladores de eventos (Event Handlers)

Quando se cria um evento em uma classe é necessário associá-lo a um manipulador de evento. A


forma tradicional de criar um manipulador de eventos é utilizar os comandos Handles e
WithEvents.

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 :

1. Criar uma variável a nível de módulo de um formulário :

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.

‘cria uma classe fora do módulo do formulário


Public Class Classe1
Public Event Iniciar(ByVal Número As Integer)
Public Sub Somar()
RaiseEvent Iniciar(1)
End Sub
End Class

‘código dentro do formulário


Public Class Form1
Inherits System.Windows.Forms.Form

‘código gerado automaticamente pelo Vb .NET


#Region " Windows Form Designer generated code "

‘Declara a variável com WithEvents que vai ser o objeto com o manipulador de eventos
Public WithEvents var As Classe1

‘Um evento Clique de um botão qualquer que utiliza a nova classe


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles Button1.Click

var = New Classe1()

var.Somar()
End Sub

‘Manipulador de evento com um código de exemplo


Private Sub var_Iniciar(ByVal Número As Integer) Handles var.Iniciar
MsgBox("Evento disparado com o nr : " & Número)
End Sub
End Class

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.

O comando AddHandler permite criar dinamicamente eventos que se conectam a manipuladores de


eventos em tempo de execução (Run time). Portanto não é preciso criar variáveis com WithEvents.

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.

Public Class Classe1


Public Event Iniciar(ByVal Número As Integer)
Public Sub Somar()
RaiseEvent Iniciar(1)
End Sub
End Class

Public Class Form1


Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button1.Click
Dim var As Classe1
var = New Classe1()
AddHandler var.Iniciar, AddressOf varIniciar_Evento
var.Somar()
End Sub

Private Sub varIniciar_Evento(ByVal Número As Integer)


MsgBox("Evento disparado com o nr : " & Número)
End Sub
End Class

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.

O comando RemoveHandler desconecta dinamicamente um evento de um manipulador de evento


em tempo de execução (Run Time), para isso é necessário seguir os passos abaixo :

1. Utilizar o comando RemoveHandler junto com o nome do emissor de eventos além do


operador AddressOf informando o nome do manipulador de eventos a ser desconectado.
Observe que a sintaxe após RemoveHandler deve ser completamente igual a AddHandler.

RemoveHandler var.Iniciar, AddressOf varIniciar_Evento

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 :

1. Declarar um manipulador de eventos na classe derivada utilizando os comandos Handles


MyBase <Nome do evento> na mesma linha do manipulador de evento a ser criado.

106
Public Class Classe1
Public Event SE(ByVal i As Integer)
' colocar métodos e propriedade aqui.
End Class

Public Class Classe2


Inherits Class1
Sub EventHandler(ByVal x As Integer) Handles MyBase.SE
' Código que manipula os eventos da Classe Básica.
End Sub
End Class

3 – Os comandos WithEvents e Handles

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

4 – Os comandos AddHandler e RemoveHandler

Os comandos AddHandler e RemoveHandler são mais flexíveis que os comandos WithEvents e


Handler pois permitem criar, adicionar, remover dinamicamente manipuladores de eventos com os
107
próprios eventos. Além disso AddHandler permite 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.

AddHandler conecta o evento de um emissor de eventos para um procedimento personalizado,


enquanto que RemoveHandler desconecta o evento de um emissor de eventos desse procedimento
personalizado. Exemplo :

AddHandler MeuObjeto.Evento1, AddressOf Me.MeuManipuladorEventos


RemoveHandler MeuObjeto.Evento1, AddressOf Me.MeuManipuladorEventos

5 – Delegar (Delegates) e o operador AddressOf

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 :

Event EventoQualquer As TipoDelegate

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.

Delegate Sub MeuProcedimento(ByVal ArgumentoQualquer as integer)

De forma resumida, Delegates significa transferir o controle de um procedimento para outros


procedimentos desde que tenham os argumentos necessários. Assim tanto AddHandler, AddressOf e
Event transferem o controle de um procedimento, no caso o evento, para outro procedimento, no
caso um manipulador de evento. Exemplo :

Delegate Sub Contar(ByVal AtéQuanto As Integer)


Public Class Classe1
Public Sub Contar1(ByVal QuantasVezes As Integer)
MsgBox("Este método sabe contar até " & QuantasVezes)
End Sub

108
End Class

Public Class classe2


Public Sub Contar2(ByVal NúmeroMáximo As Integer)
MsgBox("Esta classe possui um método que conta no máximo até " & NúmeroMáximo)
End Sub
End Class

Public Class Classe3


Public Sub Contar3(ByVal intMáximo As Integer)
MsgBox("O método da classe3 conta até " & intMáximo)
End Sub
End Class

Public Class Form1


Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button1.Click
Dim meuDelegate As Contar
Dim c1 As New Classe1()
Dim c2 As New classe2()
Dim c3 As New Classe3()
'primeiro teste
meuDelegate = AddressOf c1.Contar1
meuDelegate.Invoke(4)
'segundo teste
meuDelegate = AddressOf c2.Contar2
meuDelegate.Invoke(4)
'terceiro teste
meuDelegate = AddressOf c3.Contar3
meuDelegate.Invoke(4)
End Sub

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.

Ainda de acordo com as definições anteriores, o operador AddressOf transfere o controle de um


procedimento para outro, desta forma o objeto “meuDelegate” é uma instância do objeto “Contar”,
em seguida foi atribuído a referência de vários outros procedimentos definidos pelo operador
AddressOf.

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.

2.18.8 – Interfaces no VB .NET

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 :

Public Interface MinhaInterface


Property MinhaPropriedade(ByVal MinhaString As String)
Function MinhaFunção(ByVal MeuInteiro As Integer) As Integer
End Interface

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 :

Function MinhaFunção (ByVal MeuInteiro as Integer ) as Integer Implements


MinhaInterface.MinhaFunção

É possível criar implementações de interfaces utilizando os modificadores de acesso Public, Private,


Protected, Friend, Protected Friend, Overrides, Overloads, Overridable, MustOverride, Default e
Static. O comando Shared não é permitido neste contexto.

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 :

Sub Sub1 Implements Interface1. Sub1, Interface1.Sub2, Interface2.Sub3, Interface2.Sub4

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

Public Class ClasseImplementação1


Implements Interface1
Sub Sub1(ByVal i As Integer) Implements Interface1.sub1
MsgBox("O procedimento Sub1 da interface1 foi implementado na classe1")
End Sub
End Class

Public Class ClasseImplementação2


Implements Interface2
Dim INum As Integer = 0
Sub sub1(ByVal i As Integer) Implements Interface2.sub1
MsgBox("O procedimento Sub1 da interface2 foi implementado na classe2")
End Sub
Sub M1(ByVal x As Integer) Implements Interface2.M1
INum = x
End Sub

ReadOnly Property Num() As Integer Implements Interface2.Num


Get
Num = INum
End Get
End Property
End Class

Public Class Form1


Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button1.Click
Dim m As New ClasseImplementação1()
Dim n As New ClasseImplementação2()
m.Sub1(1)
n.sub1(1)
n.M1(4)
MsgBox(n.Num)
End Sub
End Class

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.

Observe que a Interface2 herda a definição da Interface1, mas a implementação da Interface1 e


Interface2 são independentes.

1 – Quando usar Interfaces ?

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.

Use interfaces quando :

• 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.

2.18.9 – Herança (Inherits)

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.

Os modificadores de herança utilizados pelo VB .NET são :

1. Comando Inherits – Especifica a classe básica.


2. Modificador NotInheritable – Não permite que os programadores criem classes derivadas
dessa classe.
3. Modificador MustInherit - Especifica que a classe somente deverá ser usado como classe
básica. Não é possível criar instâncias desse tipo de classe diretamente.

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

O comando MyBase tem as seguintes limitações :

• 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.

O comando MyClass permite chamar um método Overridable implementado na classe ao invés do


método susbstituído na classe derivada. Esse comando é similar ao comando Me que faz referência a
um objeto corrente.

• MyClass é um comando e não um objeto.


• MyClass faz referência a classe e seus membros herdados.
• MyClass pode ser usado com membros Shared.
• MyClass não pode ser usado em módulos.
• MyClass pode qualificar um método da classe básica que ainda não foi implementado na
classe corrente.

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

O exemplo acima demonstra a diferença de comportamento entre os comandos Me e MyClass.


Primeiro foi criada uma classe básica “ClasseBásica” que possui três métodos “MeuMétodo”,
“UseMe” e “UseMyClass” sendo que somente o primeiro método é substituível, os outros métodos
utilizam o comando Me e MyClass para ser referir ao método corrente em uso.

Em seguida a classe derivada “ClasseDerivada” substitui (Overrides) o método “MeuMétodo” com


uma nova implementação. Quando o objeto é testado, o comando Me faz referência ao método
atualmente em uso, enquanto que MyClass faz referência ao método original em uso que anula os
efeitos da versão substituída da classe derivada e permite que o compilador resolva qual a versão
invocar.

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

Protected Sub Testar()


Dim C1 As New class1()
Dim C2 As New class2()
C1.Metodo1() ' Chama o método da classe básica.
C1.Metodo2() ' Chama outro método da classe básica.
C2.Metodo1() ' Chama o método herdado da classe básica.
C2.Metodo2() ' Chama o método da classe derivada.
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button1.Click
Testar()
End Sub

Quando o procedimento Testar é executado, as mensagens abaixo são exibidas :

"Este é um método da classe básica."


"Este é um outro método da classe básica."
"Este é um método da classe básica."
"Este é um método da classe derivada."

1 – Quando usar heranças

A herança deve ser usado nos seguintes casos abaixo :

• Quando a hierarquia de uma herança “É um relacionamento” mas não aquela hierarquia


que “Tem um relacionamento”.
• Quando é necessário reutilizar um código de uma classe básica.
• Quando for necessário aplicar a mesma classe e métodos para diferentes tipos de dados.
• Quando a hierarquia de uma classe é pequena e os programadores não gostariam de
adicionar outros níveis
• Quando as mudanças de códigos da classe básica afetem outros classes derivadas.
115
Resumidamente :

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.

1.2 – Tipos de Hierarquias (“É um Relacionamento” e “Tem um Relacionamento”)

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.

1.3 – Reutilização de código

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.

1.4 – Classes derivadas e os tipos de dados

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:

MustInherit Class Produtos


Public ValorTotalArredondado As Integer
Public ValorTotalArredondadoAMenor As Integer
MustOverride Sub CalcularAumento()
End Class

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.

Este tipo de solução combina os recursos de polimorfismo baseado em herança (Inherit-based


polymorphism) e permite que os desenvolvedores que não tenham acesso ao código fonte da classe,
possam aprimorar a classe básica através da implementação de novos recursos à classe derivada.

1.5 - Hierarquia de classes

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.

1.6 – Mudanças nas classes básicas que afetam as classes derivadas

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.

2.18.10 – Construtores e Destrutores na hierarquia de classes

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 Visual Basic .NET implementa o polimorfismo através da Herança (Inherits) e através de


Interfaces (Interfaces), ao contrário de versões anteriores que somente implementavam o
polimorfismo através de Interfaces.

1 – O polimorfismo baseado em Herança

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.

Exemplo de polimorfismo baseado em herança :

Const StateRate As Double = 0.053 ' 5.3 %


Const CityRate As Double = 0.028 ' 2.8 %

Public Class BaseTax


Overridable Function CalculateTax(ByVal Amount As Double) As Double
Return Amount * StateRate.
End Function
End Class

Public Class CityTax


' Este método chama o método da classe básica
' e modifica o valor retornado.
Inherits BaseTax
Private BaseAmount As Double
Overrides Function CalculateTax(ByVal Amount As Double) As Double
BaseAmount = MyBase.CalculateTax(Amount)
Return CityRate * (BaseAmount + Amount) + BaseAmount
End Function
End Class

Sub TestPoly()
Dim Item1 As New BaseTax()
Dim Item2 As New CityTax()
ShowTax(Item1, 22.74)
ShowTax(Item2, 22.74)
End Sub

Sub ShowTax(ByVal Item As BaseTax, ByVal SaleAmount As Double)


' O argumento Item é do tipo BaseTax, mas pode-se também
' informá-lo como do tipo CityTax
Dim TaxAmount As Double
TaxAmount = Item.CalculateTax(SaleAmount)
MsgBox("A taxa é : " & Format(TaxAmount, "C"))
End Sub
120
O exemplo acima cria uma classe básica que permite que um método seja substituído. Em seguida há
uma classe derivada que substitui a implementação original da classe básica alterando o valor
retornado.

2 – Porlimorfismo baseado em Interface

A interface, já vista anteriormente, é outra forma que o VB .NET implementa o polimorfismo. A


inteface define métodos e propriedades assim como classes, mas não implementa (cria) o código de
cada procedimento, ao invés disso ele permite que a classe crie sua própria implementação.

O polimorfismo baseado em Interface é quando os métodos e propriedades definidas pela interface


são implementadas de formas diferentes em diversas classes. A grande diferença entre o
polimorfismo baseado em Interface e o polimorfismo baseado em herança é que o primeiro não
precisa utilizar uma classe básica para herdar (Comando Implements) enquanto que o último exige
uma classe básica (Comando Inherits).

Exemplo de polimorfismo baseado em Interface

Public Interface Figura


Function CalcularÁrea(ByVal X As Double, ByVal Y As Double) As Double
End Interface

Public Class Triângulo


Implements Figura
Function CalcularÁrea(ByVal X As Double, ByVal Y As Double) As _
Double Implements Figura.CalcularÁrea
' Calcula a área do triângulo.
Return 0.5 * (X * Y)
End Function
End Class

Public Class Retângulo


Implements Figura
Function CalcularÁrea(ByVal X As Double, _
ByVal Y As Double) As Double Implements Figura.CalcularÁrea
' Calcula a área do retângulo.
Return X * Y
End Function
End Class

Sub ProcessarFigura(ByVal Figura2 As Figura, ByVal X As Double, ByVal Y As Double)


MessageBox.Show("A área do objeto é " & Figura2.CalcularÁrea(X, Y))
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

2.18.12 – Criando um hierarquia de heranças

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 :

• As classes MustInherit e métodos MustOverride reduzem o risco de Classes de base frágil,


pois os detalhes da implementação ficam sob a responsabilidade da classe derivada.
• Os membros Shadow contribuem eliminando os conflitos de nomes entre os membros de
classes.
• Para criar novas funcionalidade a classe, crie novos métodos ao invés de Overloads
(Sobrecarga).

2.19 – Operações com Componentes COM

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 :

Tlbimp test3.dll /out:NameSpace1 /out:Interop1.dll

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 :

<ComClass(ComClass1.ClassId, ComClass1.InterfaceId, ComClass1.EventsId)> _


Public Class ComClass1

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.

Em seguida cole os números em cada sessão de identificação. Exemplo :

Public Const ClassId As String = "832F34A5-5CF5-403f-B4A8-428C8351FD02"


Public Const InterfaceId As String = "3D8B5BA4-FB8C-5ff8-8468-11BF6BD5CF91"

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 :

Public Sub New()


MyBase.New()
End Sub

Finalmente implemente as propriedades, métodos e eventos e compile o projeto. O VB .NET criará


um Interop Assemblie e registrará o objeto no sistema operacional.

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 :

Dim MyThread As New System.Threading.Thread(AddressOf MySub)

MyThread.Start() ‘inicia um Thread

MyThread.Abort() ‘finaliza um Thread

MyThread.Sleep () ‘Causa uma pausa no Thread


MyThread.Suspend () ‘suspende um Thread

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

Private Shared Sub Remove(ByVal x As Object)


SyncLock GetType(Cache)
End SyncLock
End Sub
End Class

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.

Public Class Palavras


Private strloc As Integer
Private RemainingString As String
Private SourceString As String
Public SourceFile As String
Public CompareString As String
Public WordCount As Integer
Private LinesCounted As Integer = 0
Public Event Status(ByVal LinesCounted As Integer, ByVal WordsMatched As Integer)
Public Event FinishedCounting(ByVal NumberOfMatches As Integer)

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

If SourceFile = System.String.Empty Or CompareString = System.String.Empty Then


MsgBox("Informe o arquivo de origem e o texto de procura.")
Exit Sub
End If

If f.Exists(SourceFile) = False Then


MsgBox("Erro ao abrir o arquivo.")
Exit Sub
End If

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 FinishedCountingEventHandler(ByVal WordCount As Integer)


' Evento disparado pelo thread que avisa que o arquivo já foi analisado..
Me.WordsCounted.Text = CStr(WordCount)
MsgBox("Fim da contagem de palavras.")
End Sub

Sub LineCountEventHandler(ByVal LinesCounted As Integer, ByVal WordsMatched As Integer)


' Evento disparado pelo thread que indica a leitura de cada linha do arquivo de texto.
Me.LinesCounted.Text = CStr(LinesCounted)
Me.WordsCounted.Text = CStr(WordsMatched)
End Sub

Dim Thread As System.Threading.Thread ‘código adicionado ao módulo de um formulário

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

Private Sub Start_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles Start.Click
IniciarThread()
End Sub

Protected Sub PararThread(Thread as System.Threading.Thread)


' Finaliza a execução do Thread
Thread.Abort()
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).

2.21 – Drivers, Pastas e Arquivos

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.

2.21.1 - A classe System.IO

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.

Algumas classes e enumerações importantes :

FileStream – classe que acessa arquivos e exibe erros dos dispositivos.


File – Classe que possui métodos para criar, apagar, mover, abrir, copiar arquivos.
Path – Classe que manipula pastas e caminhos de arquivos.
FileAccess, FileMode, FileShare, FileEnumerator, FileAttributes – Enumerações que são
utilizadas pela classe FileStream que modificam a forma como os arquivos são abertos e
manipulados.
BinaryReader – Classe que lê dados binários de um arquivo.
BinaryWriter – Classe que grava dados binários em um arquivo.

Exemplo :

Dim fs As FileStream = New FileStream("c:\dados.txt", FileMode.CreateNew)


Dim w As BinaryWriter = New BinaryWriter(fs)
Dim r As BinaryReader = New BinaryReader(fs)
Dim i As Integer

' Aloca uma série de números e armazena no Buffer


For i = 0 To 11
w.Write(CStr(i))
Next

129
' Move o ponteiro para o início do arquivo.
w.Seek(0, SeekOrigin.Begin)

' Grava o conteúdo do Buffer no console (janela do Vstudio .NET IDE).


For i = 0 To 11
Console.WriteLine(CStr(i))
Next

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()

Directory – Classe que permite manipular Pastas e Drives (dispositivos).

2.21.2 – Acessando arquivos com as funções internas do VB

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 :

FileOpen(1, "TESTE", OpenMode.Input)


' Fecha o arquivo antes de abrí-lo em outro modo.
FileClose(1)

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.

Dim LinhaDoTexto As String


Dim CanalVazio as integer

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 :

LinhaDoTexto = LinhaDoTexto & Chr(13) & Chr(10)

A função InputString deve ser usado da seguinte forma :

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.

FileOpen(1, "C:/meu.txt", OpenMode.Output)


Write(1, "Olá")
Write(1, 14)
FileClose(1)

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.

Exemplo de gravação de dados para um arquivo seqüencial :

FileOpen(1, "c:\lixo.txt", OpenMode.Output) ' Abre um arquivo output.


Print(1, "Texto qualquer.") ' Grava um texto.
PrintLine(1) ' Grava uma linha em branco.
PrintLine(1, "Zona 1", TAB(), "Zona 2") ' Grava duas colunas de texto separados por Tabulação.

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.

' Assign Boolean, Date, and Error values.


Dim aBool As Boolean
Dim aDate As DateTime
aBool = False
aDate = DateTime.Parse("February 12, 1969")

' 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

o exemplo a seguir demonstra as funções Write e WriteLine :

FileOpen(1, "c:\Lixo2.txt", OpenMode.Output) ' Abre um arquivo output.


Write(1, "Texto qualquer.") ' Grava um texto.
WriteLine(1) ' Grava uma linha em branco.
WriteLine(1, "Zona 1", TAB(), "Zona 2") ' Grava duas colunas de texto separados por Tabulação.
WriteLine(1, "Olá", " ", "Mundo") ' Separa duas strings por espaço.
WriteLine(1, SPC(5), "5 medidas de espaçamento ") ' Grava string com 5 medidas de espaço após o
‘ início do texto
WriteLine(1, TAB(10), "Olá") ' Grava uma palavra na coluna 10.

' Assign Boolean, Date, and Error values.


Dim aBool As Boolean
Dim aDate As DateTime
aBool = False
aDate = DateTime.Parse("February 12, 1969")

' 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 (.).

Um arquivo randômico (aleatório) possui registros de tamanhos pré-definidos e cada registro é


composto por um ou mais campos. Para abrir arquivos do tipo randômico é necessário criar todas as
variáveis ou estruturas de variáveis que correspondam aos dados originais do arquivo antes de abrir e
acessar os dados desse arquivo.

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.

Exemplo de criação de tipos de dados compostos :

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

‘Declara uma variável do tipo composto.


Public Empregado As DadosPessoais
' Cria uma trilha para o registro atual
Public Posição As Long
' Pega o número do último registro do arquivo.
Public ÚltimoRegistro As Long

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

' Conta 30 dígitos para o string mais 4 dígitos do tipo Integer.


FileOpen(1, "TESTE", OpenMode.Random, , , 34)
' Fecha o arquivo antes de abrir em outro modo.
FileClose(1)

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 :

Dim Meu as Pessoa


' A função determina o tamanho da estrutura
FileOpen(1, "TESTE", OpenMode.Random, , , Len(Meu))
' Fecha o arquivo antes de abrir em outro modo.
FileClose(1)

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 :

FileGetObject (NúmeroArquivo, variávelQualquer, NrRegistro)

NúmeroArquivo – É o número do arquivo aberto com a função FileOpen.


variávelQualquer – Uma variável qualquer que recebe os dados lidos do arquivo.
NrRegistro – O primeiro registro de um arquivo aleatório é 1, o segundo registro de um arquivo
aleatório é 2, o terceiro registro é 3 e assim por diante.

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

Public Sub Procurar(ByVal índice As Integer)


Try
FileOpen(1, "c:\pessoas.txt", OpenMode.Random)
Dim umaPessoa As Registro
Seek(1, índice)
FileGet(1, umaPessoa)
FileClose(1)
Console.WriteLine(umaPessoa.Nome & " " & umaPessoa.ID)
Catch
‘manipula qualquer erro de execução aqui
End Try
End Sub
Para adicionar registro basta utilizar a função FilePut informando a posição do registro sempre
posterior ao último registro do arquivo, assim ùltimaPosição + 1. Para substituir um registro use a
função FilePut informando a posição do registro a ser alterado.

Para apagar registro em arquivo aleatório deve-se seguir os passos abaixo :

1. Crie um arquivo temporário.


2. Copie os dados válidos do arquivo original para o arquivo temporário.
3. Feche o arquivo original e apague-o do disco usando a função intrínseca Kill.
4. Renomeie o arquivo secundário a função Rename.

Exemplo de criação de arquivos aleatórios, inclusão e alteração de dados :

Structure Registro
<VBFixedString(30)> Dim Nome As String
Dim ID As Integer
End Structure

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button1.Click

Dim Pessoa As Registro, NrArquivo As Integer, TamanhoRegistro As Integer

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

A mensagem será : 2 Antonio Carlos

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

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button1.Click

Dim Pessoa As Registro, NrArquivo As Integer, TamanhoRegistro As Integer

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

A mensagem ainda será : 2 Antonio Carlos

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 :

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button1.Click

Dim pixel As Byte, NrArquivo As Integer, i As Integer


Dim pixels As String

NrArquivo = FreeFile()

FileOpen(NrArquivo, "C:/Imagempreto.bmp", OpenMode.Binary)

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.

Tipo de acesso Gravação de dados Leitura de dadps


Sequential Funções Print, Função InputString
(seqüencial) PrintLine
Random (aleatório) Função FilePut Função FileGet
Binary (Binário) Função FilePut Função FileGet

2.21.3 – Acessando arquivos com FileSystemObject

O VB .NET mantém a biblioteca de Script (arquivo Scrrun.dll) de versões antigas do VB que


manipula drivers, diretórios e arquivos do sistema. Esse recurso é mais uma ferramenta baseada em
objeto conhecida como File System Object (FSO), que possui métodos; propriedades e eventos que
permite criar, excluir, alterar, mover, copiar, obter outras informações sobre arquivos e pastas e etc.
138
A única limitação é que o objeto FSO não permite criar arquivos binários, para isso é necessário usar
as técnicas descritas no capítulo anterior. Abaixo uma tabela que descreve os objetos disponíveis do
FSO :

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.

Abaixo segue uma tabela de alguns métodos do objeto FileSystemObject :

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 :

• Quando o projeto é executado em uma rede compartilhada.


• Quando o arquivo compilado é executado em uma rede compartilhada

Para manipular pastas basta utilizar os métodos abaixo :

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..

O objeto FileSystemObject permite manipular arquivos de texto seqüenciais, também conhecidos


como Arquivos de Stream, conforme abaixo :

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 :

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)


Handles Button1.Click
Dim fso As New Scripting.FileSystemObject(), fldr As Scripting.Folder
fldr = fso.CreateFolder("C:\MeuTeste")
MsgBox("Pasta Criada: " & fldr.Name)
End Sub

2.22 – Manipulando exceções (Exception)

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.

Os erros estão agrupados em 3 categorias :

1. Erros de sintaxe – Ocorre quando se digita algo errado no editor de códigos, e o VB


imediatamente verifica a sintaxe e alerta o programador sobre o erro.
2. Erros de execução (run time) – Ocorre quando o programa está compilado e em execução
mas o sistema operacional não consegue executar a tarefa, mesmo que a sintaxe esteja
correta. É necessário corrigir o problema reescrevendo outras maneiras de executar o
procedimento; recompilando e reexecutando o aplicativo.
3. Erros de lógica – Ocorre quando o aplicativo em execução exibe um resultado inesperado
em resposta a ação do usuário, normalmente quando o desenvolvedor não coloca um
procedimento que trata do assunto. É o tipo de erro mais difícil de se corrigir.

O VB .NET oferece duas formas de tratar erros (exceções) de execução no programa :

• Manipulação de erros estruturados, também conhecidos como Exceptions (exceções) – É o


método recomendado pela Microsoft para criar rotinas de tratamento de erros utilizando a
estrutura avançada de controle Try ... Catch ... Finally descendentes da linguagem C++.
• Manipulação de erros não estruturados – Método padrão de versões antigas do VB que
utiliza o comando On Error para interceptar erros de execução, entretanto esse método
influencia negativamente no desempenho do aplicativo.

2.22.1 – Manipulador estruturado de exceções

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.

O bloco Catch permite 3 opções de filtros de erros.

1. O erro é filtrado com base na exceção causada pela classe:

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.

3. O erro é filtrado com base na combinação dos filtros 1 e 2 listados acima :

Exemplo de criação de uma estrutura de tratamento de exceções :

Function LerStringsDoArquivo(ByVal NomeArquivo As String) As Collection


Dim Strings As New Collection
Dim Stream As System.IO.StreamReader = System.IO.File.OpenText(FileName) ‘Abre o arquivo.
Try
While True ' O loop é encerrado no erro da classe EndOfStreamException
' de final de arquivo.
Strings.Add(Stream.ReadLine())
End While
Catch eos As System.IO.EndOfStreamException
' Nenhuma ação necessária pois já foi alcançado o final do arquivo..
Catch IOExcep As System.IO.IOException
' Qualquer outro erro ocorreu. Exibe uma mensagem e limpa a coleção.
MsgBox(IOExcep.Message)
Strings = Nothing
Finally
Stream.Close() ' Fecha o arquivo.
End Try

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.

2.22.2 – Manipulador de exceções não estruturado

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.

O comando On Error Goto -1 desliga qualquer manipulador de exceções no procedimento.Assim


como no comando acima, -1 não é um identificador de linha portanto o fluxo do sistema não é
desviado para a linha zero do código.

Exemplos de um manipulador de erros não estruturado :

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

' Esta linha desliga o manipulador de exceções.


On Error GoTo 0
Console.WriteLine(x & "/" & y & " = " & z)

' Sai da rotina antes do início do manipulador de erros.


' Senão pode causar resultados inesperados.
Exit Sub

' Este é o manipulador de erros que trata do erro específico.


DivisãoPorZero :
' Exibe uma mensagem amigável ao usuário para que este conheça o que está acontecendo.
Console.WriteLine("Você tentou dividir um número qualquer por zero!")

' Oferece uma solução para o erro.


y=2

' O comando Resume retorna ao ponto que ocorreu o erro


' para que o aplicativo continue com a execução.
Resume

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.

3.1 – Infraestrutura NET

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.

Os perfis detalhados anteriormente são os seguintes :

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 :

Dim variávelQualquer as new System.IO ‘ O NameSpace desse exemplo é System

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

Um módulo é um arquivo .dll ou .exe. Um Assembly é um conjunto de um ou mais módulos que


foram utilizados na criação do aplicativo. Se um aplicativo está contido em um único executável
.exe, então há apenas um módulo assembly. Se o executável .exe está distribuído em dois arquivos
.dll mas que não podem ser executados separadamente, então os três arquivos juntos formam um
Assembly. Se o produto é uma bliblioteca de classe contida em um único arquivo .dll, então esse
arquivo é um Assembly.

Quando um assembly é criado e distribuído aos consumidores, um de seus módulos contém o


Assembly Manifest, que contém informações gerais sobre todo o assembly tais como a lista de
módulos existentes neste assembly, a versão do assembly, idioma, etc.

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.

Vbc MeuCódigo.vb /reference : System.Drawing.dll

Na documentação original do VB, diz-se que o argumento após o comando “/reference :” é um


assemblie, entretanto isto não está muito correto, pois este argumento é o nome de apenas um
módulo do Assembly que contém o Assembly Manifest.

Quando um projeto VB .NET é criado, o sistema automaticamente faz referência a dois assemblies
(Assembly Manifest) :

1. mscorlib.dll – Contém todos os tipos do espaço Nomeado System.


2. Microsoft.VisualBasic.dll – Contém todos os tipos encontrados na linguagem Visual Basic,
isto é o espaço nomeado Microsoft.VisualBasic.

3 – Global Assembly Cache (GAC)

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.

Todos os assemblies da infraestrutura .NET estão localizados no GAC.

4 – Common Language Specification (CLS)

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.

5- Intermediate Language (IL) e compilação Just-In-Time (JIT)

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 :

• Antes de um método ser executado.


• Na instalação do aplicativo

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).

No segundo caso, o aplicativo é compilado completamente no momento da instalação.

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.

Exemplo de uma contrução procedural :

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.

Um exemplo de construção declarativa :

Dim ObjetoQualquer as ClasseQualquer

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.

No passado, os comandos de declaração (já estudados em capítulos anteriores) eram usados


simplesmente pelo compilador e não eram compilados diretamente ao executável. Entretanto, o CLR
atual utiliza essas informações para certificar-se que a memória estará sempre utilizando a referência
de modo seguro. O compilador JIT utiliza essas informações para chamar os métodos em modo de
compilação.

Os compiladores que utilizam CLR podem trabalhar tanto com informações Procedurais como
Declarativas criando arquivos .exe ou .dll.

Todas as informações procedurais são armazenas como Linguagem Intermediária (IL) e as


informações declarativas são armazenadas como Metadados.

NO VB .NET é possível incluir vários Metadados em arquivos já compilados, esse mecanismo é


conhecido como Custom Attributes (Atributos Padrão).

7 – Gerenciamento de Memória e o Garbage Collection

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.

8 – Execução do código gerenciado

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 :

1. Escrever um programa utilizando um compilador .NET (VB, VC#, VC++). Todo o


componente escrito por um desses compiladores pode ser utilizado por outra linguagem desde
que faça parte da especificação (CLS).
2. Compilar o código. O compilador traduz o código fonte para a Linguagem intermediária (IL)
ou Microsoft Intermediate Language (MIL) que gera os metadados para o aplicativo.
3. Executar o código. Quando o código é executado, o MSIL (IL) é compilado para o código
nativo (código específico da CPU ) através do compilador Just in Time (JIT). Se for
necessário o JIT verifica o código para segurança de tipos.

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