Visual Basic.NET

Instintos Básicos

Novas características do Visual Basic .NET: Variáveis, Tipos, Matrizes e Propriedades

Escrito por Ted Pattison

Traduzido por Uana Braga

Na edição de fevereiro 2001 da revista MSDN®, eu escrevi um artigo discutindo a nova plataforma Microsoft .NET e o papel que o Visual Basic .NET desempenha em construir softwares para essa plataforma. Nesse artigo eu discuti as motivações que levaram a Microsoft a reinventar sua plataforma de desenvolvimento e as razões fundamentais para que a linguagem Visual Basic® tivesse uma revisão tão drástica. Este mês eu escreverei sobre esse artigo, então eu irei supor que você o leu (veja "Visual Basic.NET: Novo modelo de programação e melhoras na linguagem que impulsionam o poder do desenvolvimento") ou que você já tenha um alto nível de conhecimento na plataforma .NET.

Enquanto meu artigo de fevereiro era mais de uma visão geral do Common Language Runtime (CLR), este mês eu me concentrarei nas características de programação específicas que são novas no Visual Basic .NET. Uma vez que você aprendeu a utilizar todas estas características novas, eu estou certo que você concordará que o Visual Basic .NET é uma ferramenta muito melhor do que as versões anteriores. Entretanto, eu não poderia cobrir todas essas novas poderosas características em uma única coluna. Assim, a coluna deste mês será a primeira parte de uma série que se seguirá nos próximos meses.

Se você for um dos muitos programadores que gastaram boa parte da última década usando Visual Basic, o Visual Basic .NET parecerá um tanto familiar, mas ao mesmo tempo estranho. Embora você possa utilizar muitas de suas habilidades e intuições existentes, há uma série de outras que você terá que deixar de lado.

Muitas companhias têm um investimento considerável em softwares escritos em Visual Basic 6.0. Estas companhias enfrentam decisões importantes sobre o que fazer com projetos existentes. Como eu percorrerei as várias novas características do Visual Basic .NET preste atenção nos assuntos que afetam o código na transição para o Visual Basic .NET. Como você verá, há muitos assuntos a considerar. Embora a linguagem seja mais consistente, poderosa e elegante, você achará que transformar um projeto bem escrito em Visual Basic 6.0 em um projeto em Visual Basic .NET requer muito esforço e perícia. Com certeza, você terá a boa sorte de começar um projeto em Visual Basic .NET do zero em um futuro não muito distante.

Novas Facilidades

Eu gostaria de começar introduzindo a nova sintaxe para declarar e inicializar uma variável com uma única linha do código. Enquanto muitos novos programadores provavelmente terão essa sintaxe como certa, aqueles que estão acostumados a usar duas linhas para declarar e inicializar suas variáveis desde os velhos tempos do Visual Basic 1.0 ficarão muito gratos.

Aqui estão três exemplos que mostram a vantagem da sintaxe do Visual Basic .NET.

Dim x As Integer = 10 
Dim obj1 As Class1 = New Class1 
Dim obj2 As New Class2 

Note que, ao contrário das duas primeiras linhas, a última linha neste exemplo é uma sintaxe válida tanto no Visual Basic 6.0 como no Visual Basic .NET. Entretanto, é importante observar que essa sintaxe é tratada diferentemente no Visual Basic .NET. Com o Visual Basic 6.0, muitos desenvolvedores experientes olham feio para essa sintaxe porque ela resulta numa inicialização mais vagarosa, que pode causar um desempenho mais lento e pode também dificultar a depuração de uma aplicação.

A boa notícia é que essa sintaxe não causa uma inicialização vagarosa no Visual Basic .NET e, portanto, não apresenta os mesmos problemas. Ao olhar o exemplo anterior, você pode notar que a terceira linha, que usa a sintaxe válida no Visual Basic 6.0, é efetivamente a mesma que a linha anterior a ela. Quando você usa a sintaxe nessa forma, o objeto começa criado e inicializado e, depois, é atribuído para sua variável antes que a linha seguinte comece a ser executada.

A nova e útil sintaxe de iniciação pode também ser usada para campos dentro da definição de uma classe ou de uma estrutura. Como você pode provavelmente supor, a sintaxe se parece com isso:

Class Class1 
Private Field1 As Integer = 10 
Public Field2 As Class1 = New Class1
End Class 

Note também que quando você declarar várias variáveis na mesma linha, elas sempre têm o mesmo tipo. Veja esse exemplo:

Dim x, y, z As Integer 

As três variáveis estão definidas como inteiras. Você não precisa mais se preocupar com as duas primeiras variáveis serem definidas acidentalmente como variantes. De fato, você nunca teve que se preocupar sobre qualquer variável ser definida como uma variante porque esse tipo não faz parte do modelo de programação de CLR. O tipo universal agora é o System.Object.

Uma das minhas favoritas adições à sintaxe do Visual Basic .NET é a possibilidade de passar um valor de retorno de uma função a quem a chamou usando a instrução Return. Dê uma olhada na seguinte função:

Function MyFunction() As String 
Return "Este é meu valor de retorno" 
End Function 

Como é o caso de outras línguas tais como C, a instrução Return pára a execução do método e retorna o controle para trás, ou seja, para quem o chamou. Eu acho a instrução Return muito mais conveniente do que o que você era forçado a usar em versões mais antigas do Visual Basic. Como você recordará, em versões mais antigas um valor de retorno é passado para quem o chamou atribuindo-o ao nome da função dentro do corpo da função. Com a instrução Return do Visual Basic .NET, você muda o nome de uma função ou cópia e cola o código de um método para outro sem a necessidade procurar através do corpo da função e mudar cada ocorrência do nome da função.

Removendo Inconsistências

Como eu comentei em meu artigo de fevereiro, o Visual Basic .NET não requer e não permite que você use a palavra-chave Set ao atribuir um objeto a uma variável da referência. Este é um ponto em que os compiladores para Visual Basic 6.0 e Visual Basic .NET entram em discordância total. Examine o seguinte código:

Dim obj1, obj2, obj3, obj4 As Class1 
obj1 = New Class1 
obj2 = obj1 
Set obj3 = New Class1 
Set obj4 = obj3 

A segunda e a terceira linhas representam um código válido no Visual Basic .NET, porém resultam em erros de tempo de execução quando compiladas em Visual Basic 6.0. A quarta e quinta linhas representam um código que é válido em Visual Basic 6.0, porém não compilarão no Visual Basic .NET. Como você pode imaginar, a instrução Set requer alguma atenção ao migrar do Visual Basic 6.0 para o Visual Basic .NET.

Após escrever códigos usando Visual Basic .NET por mais de seis meses, eu continuo adicionando as instruções Set onde não devo. É difícil livrar-se dos velhos hábitos. Houve também épocas onde meus empenhos profissionais me forçaram a escrever códigos usando o Visual Basic .NET e

Visual Basic 6.0 durante um mesmo dia. É realmente difícil saltar de uma tecnologia para outra.

Uma outra mudança sintática que aumenta o assunto de migração é o uso de parênteses na passagem de parâmetros. Durante anos, muitos de você acostumaram-se às regras e exclusividades de se chamar uma função contra as de se chamar um procedimento. A equipe do Visual Basic .NET decidiu que era hora para uma mudança que promovesse maior coerência.

As regras de passagem de parâmetros no Visual Basic .NET são muito simples. Sempre que você chama uma função ou um procedimento em que quem está chamando irá passar um ou mais parâmetros, os parâmetros devem ser passados entre parênteses. Ao chamar uma função ou um procedimento que não necessite de nenhum parâmetro, o uso do parêntese é opcional. Você tem que concordar que essas regras são muito mais fáceis de aprender e muito mais claras do que aquelas de versões mais antigas do Visual Basic.

Também é importante notar que a convenção padrão para a passagem de parâmetro mudou. Por exemplo, como é passado o parâmetro quando um método é definido nesta maneira?

Sub Method1(Param1 As Integer) 
' implementação 
End Sub 

Em todas as versões anteriores do Visual Basic, Param1 é passado por referência. Isso significa que a execução de Method1 poderia fazer uma mudança a este parâmetro inteiro que seria vista por quem o chamou. No Visual Basic .NET, a convenção padrão de passagem de parâmetro foi mudada para ByVal. Isso significa que uma cópia de Param1 é passada à execução de Method1 e as mudanças nunca são visíveis a quem o chamou. Esta mudança na convenção padrão de passagem pode obviamente quebrar a semântica de algum código escrito em Visual Basic 6.0 quando este for convertido para Visual Basic .NET.

Note que o parâmetro que está sendo passado no exemplo anterior é do tipo Value. Os tipos primitivos como Byte, Integer, Double e Boolean são todos exemplos de Values. Enumerações e estruturas definidas pelos usuários são também exemplos Values. Os exemplos de tipo Value são sempre copiados quando são passados como ByVal.

As coisas funcionam muito diferente quando você está passando os parâmetros baseados em tipos de classe. Os parâmetros baseados em classes são tipos de referência ao contrário dos tipos de valor. Eles são usados para passar referências de objetos. Por exemplo, se você chamar um método passando uma referência de objeto como parâmetro do tipo ByVal, a execução do método pode mudar o estado do objeto. Esta mudança no estado seria visível a quem chamou o método. Em conseqüência disso, é muito importante fazer a distinção entre tipo de valor e tipo referência quando você estiver projetando parâmetros que devem ser declarados como ByVal ou como ByRef.

Enquanto o uso opcional de parâmetros ainda for permitido em métodos, este será um ponto que requer uma atenção especial. Ao contrário do Visual Basic 6.0, o uso opcional de parâmetros requer agora um valor padrão. Seguindo as mesmas linhas, o Visual Basic .NET não suporta a função IsMissing. Isto significa que você não pode diferenciar entre uma chamada que omita o parâmetro e uma chamada que passe o valor padrão como parâmetro.

Se você estiver considerando projetar métodos com parâmetros opcionais, você deve avaliar se o uso de métodos sobrecarregados será satisfatório. Uma vez que você aprendeu os benefícios e a sintaxe do método sobrecarregado, você pode decidir interromper o projeto de métodos com parâmetros opcionais.

Níveis Superiores de Tipos Seguros

A maioria dos desenvolvedores que são sérios defensores do Visual Basic inclui a instrução Option Explicit no topo de todo arquivo fonte baseado no Visual Basic. O uso do Option Explicit sempre separou verdadeiros desenvolvedores de usuários ocasionais. Ao contrário das versões anteriores, o Visual Basic .NET habilita a opção Option Explicit por padrão.

Option Strict é outra característica de tempo de compilação que é habilitada como padrão no Visual Basic .NET. A característica Option Strict rejeita conversões limitantes implícitas. Uma conversão limitante é uma conversão que poderia resultar na perda de dados ou de precisão. Olhe o seguinte exemplo:

Dim x As Double 
x = 20.1 
Dim y As Integer 
' conversão limitante implícita 
y = x ' não compila sob o Option Strict 

Este código compila em Visual Basic 6.0. Entretanto, não compila no Visual Basic .NET quando o Option Strict está habilitado. O Option Strict reforça uma política na qual o programador deve deixar clara a finalidade de cada tipo. Uma conversão explícita permite que o programador diga ao compilador, "Eu sei que há uma conversão limitante, mas eu não espero que isso seja um problema". Aqui está como reescrever o código anterior de modo que compile:

Dim x As Double 
x = 20.1 
Dim y As Integer 
' conversão limitante explicita 
y = CInt(x) ' compila sob o Option Strict 

Uma outra grande mudança na linguagem é que a instrução If agora é "curto circuitada". Isto representa uma valiosa otimização, mas novamente é importante entender como isso poderia interromper o código baseado em Visual Basic 6.0 quando transferido para o Visual Basic .NET. Olhe o seguinte código:

If Function1() And Function2() Then 
' bloco de instrução 
End If 

Se Function1 for avaliada como falso, é realmente necessário executar e avaliar Function2 para determinar se executa as instruções dentro do bloco If Then? A resposta, obviamente, é não. Entretanto, versões mais antigas do Visual Basic não executavam o If "curto circuitado" e, conseqüentemente, Function2 seria executado em todas as situações. O Visual Basic .NET leva a um curto circuito que faz com que Function2 não seja executada se Function1 retornar falso. Isso é, contudo, uma outra diferença de comportamento que poderia impedir que o código baseado no Visual Basic 6.0 funcione corretamente quando compilado no Visual Basic .NET.

Nesse momento, eu gostaria de indicar uma outra melhoria para tipo seguro dentro da linguagem. Você deve notar que o exemplo de código anterior não compilará se Function1 ou Function2 retornarem qualquer tipo diferente de Boolean. Com os novos níveis superiores dos tipos seguros, você não pode mais executar testes condicionais com valores inteiros. Por exemplo, o código seguinte, usado geralmente em Visual Basic 6.0, não compilará no Visual Basic .NET.

Dim x As Integer 
' x é 0 se falso ou qualquer outro valor se verdadeiro 
If x Then 
' execute o bloco de instruções
End If 

Os novos tipos seguros reforçados por Option Strict requerem que você trabalhe exclusivamente com valores booleanos quando você usa blocos com, por exemplo, instruções If e loops com Do.

Quando utilizar operadores lógicos de comparação como Not, And, Or, e Xor, você também estará restrito a usar valores booleanos como entrada e saída. Isso é diferente das versões anteriores do Visual Basic onde estes operadores poderiam ser usados tanto para comparações lógicas quanto para comparações bit a bit. Aqui está um outro exemplo de código que compila em Visual Basic 6.0, mas resulta em um erro de tempo de execução de conversão no Visual Basic .NET.

Dim x As Integer 
Dim y As Integer 
Dim z As Integer 
x = 3 
Y = 6 
z = x And y ' não compila 

O Visual Basic .NET fornece quatro novos operadores de comparação bit a bit: BitNot, BitAnd, BitOr, e BitXor. Estes operadores permitem que você execute operações de comparação de bits de forma segura quanto aos tipos. Por exemplo, você usaria um desses operadores para fazer um OR nos bits de dois valores inteiros ou aplicaria uma máscara de bit. Aqui está um exemplo de como usar BitOr e BitAnd:

Dim x As Integer = 3 
Dim y As Integer = 6 
Dim z As Integer 
' OR bits juntos 
z = x BitOr y ' z agora igual a 7 
' AND para encontrar intersecção de bits 
z = x BitAnd y ' z agora igual 2 

Programando Matrizes

Houve uma mudança razoavelmente dramática à sintaxe fundamental para declarar e usar matrizes. Primeiramente, as matrizes são sempre baseadas em zero. Você não pode mais criar uma matriz com um limite inferior menor que 1. Conseqüentemente, a instrução Option Base foi removida da linguagem.

Além disso, quando você declara uma matriz você deve inicializá-la com seu número de elementos em vez de seu limite superior. Aqui está aqui um exemplo simples:

' declarar uma matriz com 3 elementos de 0 a 2 
Dim array1(3) As Integer 
array1(0) = 2 
array1(1) = 4 
array1(2) = 8 

Se a matriz do exemplo anterior fosse declarada em Visual Basic 6.0, ela teria quatro elementos com as posições que variando de 0 a 3. No Visual Basic .NET, essa matriz tem três elementos com as posições variando de 0 a 2. Sob o Visual Basic .NET seu código experimentará uma exceção em tempo de execução se tentar acessar um elemento na posição 3 na matriz mencionada anteriormente, veja:

' indexado fora da taxa de exceção 
array1(3) = 16 

O Visual Basic .NET trouxe uma nova sintaxe para inicialização de matrizes. Você pode declarar uma matriz em uma única linha de código, como a seguinte:

' nova sintaxe de inicialização de matriz 
Dim array1 As Integer() = {2, 4, 8} 

Como nas versões mais antigas do Visual Basic, você pode enumerar direto uma matriz usando o loop For Each.

Dim x As Integer 
For Each x In array1 
Console.WriteLine(x) 
Next 

Alternativamente, você pode fazer um loop sobre uma matriz usando o loop For e a propriedade do comprimento da matriz, assim:

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

O CLR e o Visual Basic .NET suportam matrizes multidimensionais em adição às matrizes unidimensionais. Por exemplo, se você quer uma matriz bidimensional, você pode defini-la utilizando uma dessas três técnicas:

Dim array1(2, 2) As Integer 
Dim array2 As Integer(,) 
Redim array2(2, 2) 
Dim array3 As Integer(,) = { {12, 24}, {10, 20} } 

Quando se trata de programação com matrizes, você deve entender que não foi só a sintaxe que mudou. A maneira que as matrizes são tratadas pelo tempo de execução subjacente é totalmente diferente. No CLR, as matrizes são sempre alocadas como objetos baseados em empilhamento. Quando você adiciona um parâmetro a um método baseado em um tipo de matriz, significa que você está passando uma referência de objeto ao contrário de passar uma cópia da matriz.

Aqui estão três métodos que passam referências de matrizes para frente e para trás:

Sub Method1(ByRef array1 As Integer()) 
' implementação
 End Sub 
Sub Method2(ByVal array1 As Integer()) 
' implementação 
End Sub 
Sub Method3(ByVal array1 As Integer(,)) 
' implementação
End Sub 

O Method1 passa uma referência de matriz em ambas as direções e seria usado tipicamente para passar uma matriz de referência de volta para quem o solicitou. Os Method2 e Method3 passam matrizes de referência de quem o chamou à execução do método. Note que o parâmetro no Method2 é definido como uma matriz unidimensional, enquanto o parâmetro no Method3 é definido como uma matriz bidimensional.

Cada objeto matricial herda seus detalhes de implementação centrais e definições de membros públicos da classe de fornecimento de sistema, System.Array. Você deve checar a documentação do System.Array no SDK da plataforma .NET. Esta classe fornece funcionalidade interna executando tarefas comuns orientadas a matrizes tais como limpar, copiar, clonar, procurar e ordenar. Aqui está um exemplo de uso de alguns dos métodos expostos pela classe de System.Array:

Dim array1 As Integer() = {4, 2, 8, 1} 
Dim array2 As Integer() 
' clonando uma matriz 
array2 = CType(array1.Clone(), Integer()) 
' limpando uma matriz 
System.Array.Clear(array1, 0, array1.Length) 
' ordenando uma matriz 
System.Array.Sort(array2) 
' ordenando uma matriz na ordem inversa 
System.Array.Reverse(array2) 

Note que você pode executar uma operação de ordenação em qualquer matriz contanto que o tipo da matriz seja baseado na execução da interface IComparable. Tipos centrais do CLR tais como o Integer, Double, String, e Date foram projetados para serem executados na IComparable. Se você quiser ordenar matrizes baseadas em seus tipos personalizados, você necessita simplesmente implementar a interface IComparable em suas próprias classes e estruturas.

Uma nova sintaxe para propriedades

Eu tenho certeza que você está familiarizado com definições e uso de propriedades nas versões mais antigas do Visual Basic. Embora as motivações para usar as propriedades sejam exatamente as mesmas, a sintaxe para defini-las mudou. Propriedades agora são definidas em termos de uma propriedade de construção que tem um bloco Set e/ou um bloco Get. O código seguinte é um exemplo de uma classe com um campo confidencial e uma propriedade pública:

Class Class1 
' campo privado 
Private m_Name As String 
' propriedade publica 
Public Property Name As String 
Get 
Return m_Name 
End Get 
Set 
If Value <> "" Then ' valor é uma variável interna 
m_Name = Value 
End If 
End Set 
End Property 
End Class 

Observe que o bloco Set contém uma variável interna chamada Value. O Visual Basic .NET usa essa variável interna para passar o valor da propriedade determinada pelo cliente para a implementação da propriedade dentro do bloco Set. Note também que com o Visual Basic .NET, não há nenhuma confusão sobre quando usar a propriedade Set contra a propriedade Let.

Uma propriedade pode ser ReadWrite, ReadOnly ou WriteOnly. O exemplo mostrado anteriormente demonstra uma propriedade ReadWritre. Os exemplos seguintes mostram como criar uma propriedade ReadOnly e WriteOnly, respectivamente.

' Uma propriedade ReadOnly possui Get mas não possui Set 
Public ReadOnly Property FullName as String 
Get 
Return m_FirstName & " " & m_LastName 
End Get 
End Property 
' Uma propriedade WriteOnly possui Set mas não possui Get Public WriteOnly Property Password as String 
Set 
m_Password = Value 
End Set 
End Property 

Observe que você deve usar as palavras-chave ReadOnly e WriteOnly quando você decidir omitir o bloco Get ou o bloco Set.

Propriedades Indexadas e Propriedades Default

Uma propriedade pode ser definida com uma ou mais indexações. Isso permite a uma propriedade exibir matrizes - como qualidade. Por exemplo, veja a classe seguinte:

Class Class1 
Private m_Names As String() = {"Ted", "Fred", "Jed"} 
' uma propriedade indexada 
Readonly Property Item(Index As Integer) As String 
Get 
Return m_Names(Index) 
End Get 
End Property 
End Class 

Do lado do cliente, você pode acessar a propriedade Item com o seguinte código:

Dim obj As New Class1 
Dim s1 String 
s1 = obj.Item(0) 

Levando esse exemplo um passo mais adiante, você pode marcar uma propriedade de indexação como uma propriedade default para uma classe. Para fazer isso, você simplesmente adiciona a palavra chave Default no último exemplo, assim:

Default Readonly Property Item(Index As Integer)... 

Uma vez marcada uma propriedade de indexação com a palavra-chave Default, o código do lado do cliente pode omitir o nome da propriedade e usar uma referencia de objeto como se fosse uma matriz:

Dim obj As New Class1 
Dim s1 String 
s1 = obj(0) 

Você deve saber uma importante restrição com relação às propriedades default. Uma propriedade que não tenha nenhuma indexação não pode ser marcada como uma propriedade default. Essa restrição aparece no Visual Basic .NET porque você não pode usar a instrução Set para designar uma referencia de objeto. Como a instrução Since foi removida da linguagem, propriedades default não indexadas criariam uma ambigüidade que pode não ser solucionada.

Conclusão

Como você viu, a Visual Basic .NET é uma linguagem muito diferente das suas antecessoras em vários aspectos. É muito mais consistente e com tipos seguros. Além do mais, no Visual Basic .NET é mais fácil escrever códigos manejáveis e legíveis. E mesmo que você leve algum tempo extra se acostumando com todas essas checagens extras de tempo de execução, isso irá lhe economizar muito tempo procurando erros durante seus testes e ciclos de depuração.

A boa notícia é que tem se transformado numa linguagem melhor e mais poderosa. A má notícia é que um projeto não trivial escrito em Visual Basic 6.0 irá necessitar de bastante trabalho se você planeja migrar para o Visual Basic .NET.

Embora a coluna desse mês tratou de muitas mudanças centrais na sintaxe do Visual Basic, há muito mais a cobrir. Eu ainda não discuti nenhuma das novas características orientadas a objetos como métodos compartilhados, métodos sobrecarregados, construções parametrizadas, e herança. Assim, fica direcionada a próxima edição da série Instintos Básicos.

Envie dúvidas e comentários para Ted em instinct@microsoft.com.

Ted Pattison é instrutor e pesquisador do DevelopMentor , onde comanda o currículo de Visual Basic. A segunda edição do livro de Ted , Programming Distributed Applications with COM and Microsoft Visual Basic 6.0 , foi publicada pela Microsoft Press em Junho de 2000.

Edição de Maio de 2001 da Revisa MSDN.

Faça o download deste documento

Instintos Básicos

downl.gif formato Word, 92 Kb