Novidades do Visual Basic
Este tópico lista os nomes dos principais recursos para cada versão do Visual Basic, com descrições detalhadas das funcionalidades novas e aprimoradas nas versões mais recentes da linguagem.
Versão atual
Visual Basic 16.9 / Visual Studio 2019 Versão 16.9
Para as novas funcionalidades, consulte Visual Basic 16.9.
Você pode baixar o SDK mais recente do .NET na página de downloads do .NET.
Versões anteriores
Visual Basic 16.0 / Visual Studio 2019 Versão 16.0
Para as novas funcionalidades, consulte Visual Basic 16.0.
Visual Basic 15.5 / Visual Studio 2017 Versão 15.5
Para as novas funcionalidades, consulte Visual Basic 15.5.
Visual Basic 15.3 / Visual Studio 2017 Versão 15.3
Para as novas funcionalidades, consulte Visual Basic 15.3.
Visual Basic 15/Visual Studio 2017
Para as novas funcionalidades, consulte Visual Basic 2017.
Visual Basic/Visual Studio 2015
Para as novas funcionalidades, consulte Visual Basic 14.
Visual Basic/Visual Studio 2013
Visualizações de tecnologia da Plataforma do Compilador .NET (“Roslyn”)
Visual Basic/Visual Studio 2012
palavras-chave Async
e await
, iteradores, atributos de informações do chamador
Visual Basic, Visual Studio 2010
Propriedades autoimplementadas, inicializadores de coleção, continuação de linha implícita, covariância/contravariância genérica, acesso ao namespace global
Visual Basic/Visual Studio 2008
LINQ (consulta integrada à linguagem), literais XML, inferência de tipos de variável local, inicializadores de objeto, tipos anônimos, métodos de extensão, inferência de tipos var
local, expressões lambda, operador if
, métodos parciais, tipos de valor anulável
Visual Basic/Visual Studio 2005
O tipo My
e tipos auxiliares (acesso ao aplicativo, computador, sistema de arquivos, rede)
Visual Basic / Visual Studio .NET 2003
Operadores bit shift, declaração de variável de loop
Visual Basic / Visual Studio .NET 2002
A primeira versão do Visual Basic .NET
Visual Basic 16.9
O Visual Basic 16.9 permite o consumo de propriedades somente init.
Visual Basic 16.0
O Visual Basic 16.0 se concentra em fornecer mais recursos do Visual Basic Runtime (microsoft.visualbasic.dll) para o .NET Core e é a primeira versão do Visual Basic focada no .NET Core. Muitas partes do Runtime do Visual Basic dependem do WinForms e elas serão adicionadas em uma versão posterior do Visual Basic.
Comentários permitidos em mais lugares dentro de instruções
No Visual Basic 15.8 e versões anteriores, os comentários só são permitidos em linhas em branco, no final de uma instrução ou em locais específicos dentro de uma instrução em que uma continuação de linha implícita é permitida. A partir do Visual Basic 16.0, os comentários também são permitidos após continuações de linha explícitas e dentro de uma instrução em uma linha começando com um espaço seguido de um sublinhado.
Public Sub Main()
cmd.CommandText = ' Comment is allowed here without _
"SELECT * FROM Titles JOIN Publishers " _ ' This is a comment
& "ON Publishers.PubId = Titles.PubID " _
_ ' This is a comment on a line without code
& "WHERE Publishers.State = 'CA'"
End Sub
Ponto flutuante otimizado para a conversão de inteiro
Nas versões anteriores do Visual Basic, a conversão de valores Duplos e Únicos como inteiros apresentava um desempenho relativamente baixo. O Visual Basic 15.8 melhora significativamente o desempenho das conversões de ponto flutuante para inteiros quando você passa o valor retornado por qualquer um dos seguintes métodos para uma das funções de conversão de inteiros intrínsecas do Visual Basic (CByte, CShort, CInt, CLng, CSByte, CUShort, CUInt, CULng) ou quando o valor retornado por qualquer um dos métodos a seguir é implicitamente convertido em um tipo integral quando Opção Strict está definida como Off
:
- Conversion.Fix(Double)
- Conversion.Fix(Object)
- Conversion.Fix(Single)
- Conversion.Int(Double)
- Conversion.Int(Object)
- Conversion.Int(Single)
- Math.Ceiling(Double)
- Math.Floor(Double)
- Math.Round(Double)
- Math.Truncate(Double)
Essa otimização permite que o código seja executado mais rapidamente – até duas vezes mais rápido para o código que faz um grande número de conversões para tipos de inteiro. O exemplo a seguir ilustra algumas chamadas de método simples que são afetadas por essa otimização:
Dim s As Single = 173.7619
Dim d As Double = s
Dim i1 As Integer = CInt(Fix(s)) ' Result: 173
Dim b1 As Byte = CByte(Int(d)) ' Result: 173
Dim s1 AS Short = CShort(Math.Truncate(s)) ' Result: 173
Dim i2 As Integer = CInt(Math.Ceiling(d)) ' Result: 174
Dim i3 As Integer = CInt(Math.Round(s)) ' Result: 174
Observe que isso trunca em vez de arredondar os valores de ponto flutuante.
Visual Basic 15.5
Argumentos nomeados que não estejam à direita
No Visual Basic 15.3 e nas versões anteriores, quando uma chamada de método incluía argumentos por posição e por nome, os argumentos posicionais tinham que preceder os argumentos nomeados. A partir do Visual Basic 15.5 os argumentos posicionais e nomeados podem aparecer em qualquer ordem, desde que todos os argumentos, até o último argumento posicional, estejam na posição correta. Isso é especialmente útil quando os argumentos nomeados são usados para tornar o código mais legível.
Por exemplo, a seguinte chamada de método tem dois argumentos posicionais entre um argumento nomeado. O argumento nomeado deixa claro que o valor 19 representa uma idade.
StudentInfo.Display("Mary", age:=19, #9/21/1998#)
Private Protected
Modificador de acesso de membro
Essa nova combinação de palavra-chave definirá um membro que é acessível por todos os membros em sua classe recipiente, bem como por tipos derivados da classe recipiente, mas somente se eles também forem encontrados no assembly de contenção. Como estruturas não podem ser herdadas, Private Protected
só pode ser aplicado aos membros de uma classe.
Separador hex/binário/octal à esquerda
O Visual Basic 2017 agora tem suporte para o caractere de sublinhado (_
) como um separador de dígito. A partir do Visual Basic 15.5, você pode usar o caractere de sublinhado como separador à esquerda entre o prefixo e os dígitos binários, hexadecimais ou octais. O exemplo a seguir usa um separador de dígito à esquerda para definir 3.271.948.384 como um número hexadecimal:
Dim number As Integer = &H_C305_F860
Para usar o caractere de sublinhado como separador à esquerda, você deve adicionar o seguinte elemento ao arquivo de projeto do Visual Basic (*.vbproj):
<PropertyGroup>
<LangVersion>15.5</LangVersion>
</PropertyGroup>
Visual Basic 15.3
Quando você atribui o valor de elementos de tupla com base em variáveis, o Visual Basic infere o nome dos elementos de tupla dos nomes de variável correspondentes; não é necessário nomear explicitamente um elemento de tupla. O exemplo a seguir usa a inferência para criar uma tupla com três elementos nomeados, state
, stateName
e capital
.
Const state As String = "MI"
Const stateName As String = "Michigan"
Const capital As String = "Lansing"
Dim stateInfo = (state, stateName, capital)
Console.WriteLine($"{stateInfo.stateName}: 2-letter code: {stateInfo.State}, Capital {stateInfo.capital}")
' The example displays the following output:
' Michigan: 2-letter code: MI, Capital Lansing
Opções adicionais do compilador
O compilador de linha de comando do Visual Basic agora é compatível com as opções do compilador -refout e -refonly para controlar a saída de assemblies de referência. A -refout define o diretório de saída do assembly de referência e a -refonly especifica que somente um assembly de referência deve ser produzido pela compilação.
Visual Basic 15
As tuplas são uma estrutura de dados leve que é mais comumente usada para retornar vários valores de uma única chamada de método. Normalmente, para retornar vários valores de um método, você precisa realizar uma das seguintes ações:
Defina um tipo personalizado (uma
Class
ouStructure
). Esta é uma solução pesada.Definir um ou mais parâmetros
ByRef
, além de retornar um valor do método.
O suporte do Visual Basic para tuplas permite definir rapidamente uma tupla, opcionalmente atribuir nomes semânticos para seus valores e recuperar rapidamente seus valores. O exemplo a seguir encapsula uma chamada para o método TryParse e retorna uma tupla.
Imports System.Globalization
Public Module NumericLibrary
Public Function ParseInteger(value As String) As (Success As Boolean, Number As Integer)
Dim number As Integer
Return (Integer.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, number), number)
End Function
End Module
O chamador pode então chamar o método e manipular a tupla retornada com o código semelhante ao seguinte.
Dim numericString As String = "123,456"
Dim result = ParseInteger(numericString)
Console.WriteLine($"{If(result.Success, $"Success: {result.Number:N0}", "Failure")}")
Console.ReadLine()
' Output: Success: 123,456
Literais binários e os separadores de dígito
Você pode definir um literal binário usando o prefixo &B
ou &b
. Além disso, você pode usar o caractere de sublinhado, _
, como um separador de dígitos para melhorar a legibilidade. O exemplo a seguir usa as duas funcionalidades para atribuir um valor Byte
e exibi-lo como um número decimal, hexadecimal e binário.
Dim value As Byte = &B0110_1110
Console.WriteLine($"{NameOf(value)} = {value} (hex: 0x{value:X2}) " +
$"(binary: {Convert.ToString(value, 2)})")
' The example displays the following output:
' value = 110 (hex: 0x6E) (binary: 1101110)
Para obter mais informações, consulte a seção "Atribuições de literal" dos tipos de dados Byte, Integer, Long, Short, SByte, UInteger, ULong e UShort.
Suporte para valores retornados por referência em C#
Começando com o C# 7.0, o C# é compatível com valores retornados de referência. Isto é, quando o método de chamada recebe um valor retornado por referência, ele pode alterar o valor da referência. O Visual Basic não permite a criação de métodos com valores retornados de referência, mas isso não permite o consumo e a modificação de valores de retorno de referência.
Por exemplo, a classe Sentence
a seguir escrita em C# inclui um método FindNext
que localiza a próxima palavra em uma sentença que começa com uma subcadeia de caracteres especificada. A cadeia de caracteres é retornada como um valor retornado de referência e uma variável Boolean
passada pela referência para o método indica se a pesquisa foi bem-sucedida. Isso significa que, além de ler o valor retornado, o chamador também pode modificá-lo e essa modificação é refletida na Sentence
classe.
using System;
public class Sentence
{
private string[] words;
private int currentSearchPointer;
public Sentence(string sentence)
{
words = sentence.Split(' ');
currentSearchPointer = -1;
}
public ref string FindNext(string startWithString, ref bool found)
{
for (int count = currentSearchPointer + 1; count < words.Length; count++)
{
if (words[count].StartsWith(startWithString))
{
currentSearchPointer = count;
found = true;
return ref words[currentSearchPointer];
}
}
currentSearchPointer = -1;
found = false;
return ref words[0];
}
public string GetSentence()
{
string stringToReturn = null;
foreach (var word in words)
stringToReturn += $"{word} ";
return stringToReturn.Trim();
}
}
Em sua forma mais simples, você pode modificar a palavra encontrada na frase usando um código semelhante ao seguinte. Observe que você não está atribuindo um valor ao método, mas para a expressão que o método retorna, que é o valor retornado de referência.
Dim sentence As New Sentence("A time to see the world is now.")
Dim found = False
sentence.FindNext("A", found) = "A good"
Console.WriteLine(sentence.GetSentence())
' The example displays the following output:
' A good time to see the world is now.
Um problema com esse código, no entanto, é que, se uma correspondência não for encontrada, o método retornará a primeira palavra. Como o exemplo não examina o valor do argumento Boolean
para determinar se uma correspondência foi encontrada, ele modificará a primeira palavra se não houver nenhuma correspondência. O exemplo a seguir corrige isso substituindo a primeira palavra por ela mesma se não há nenhuma correspondência.
Dim sentence As New Sentence("A time to see the world is now.")
Dim found = False
sentence.FindNext("A", found) = IIf(found, "A good", sentence.FindNext("B", found))
Console.WriteLine(sentence.GetSentence())
' The example displays the following output:
' A good time to see the world is now.
Uma solução melhor é usar um método auxiliar para o qual o valor retornado de referência é passado por referência. O método auxiliar pode modificar o argumento passado para ele por referência. O exemplo a seguir faz isso.
Module Example
Public Sub Main()
Dim sentence As New Sentence("A time to see the world is now.")
Dim found = False
Dim returns = RefHelper(sentence.FindNext("A", found), "A good", found)
Console.WriteLine(sentence.GetSentence())
End Sub
Private Function RefHelper(ByRef stringFound As String, replacement As String, success As Boolean) _
As (originalString As String, found As Boolean)
Dim originalString = stringFound
If found Then stringFound = replacement
Return (originalString, found)
End Function
End Module
' The example displays the following output:
' A good time to see the world is now.
Para obter mais informações, consulte Reference return values (Valores retornados de referência).
Visual Basic 14
Você pode obter o nome da cadeia de caracteres não qualificada de um tipo ou de um membro para uso em uma mensagem de erro sem realizar hard-coding de uma cadeia de caracteres. Isso permite que seu código permaneça correto ao refatorar. Esse recurso também é útil para conectar links MVC do tipo modelo-exibição-controlador e acionar eventos de alteração de propriedade.
Interpolação de cadeia de caracteres
Você pode usar expressões de interpolação de cadeia de caracteres para construir cadeias de caracteres. Uma expressão de cadeia de caracteres interpolada parece com uma cadeia de caracteres de modelo que contém expressões. Uma cadeia de caracteres interpolada é mais fácil de entender, em relação a argumentos, do que a formatação composta.
Acesso de membro nulo condicional e indexação
Você pode testar a nulidade de uma maneira sintática muito simples antes de executar uma operação de acesso de membro (?.
) ou índice (?[]
). Esses operadores ajudam a escrever menos código para lidar com verificações de nulidade, especialmente para entrar em estruturas de dados. Se a referência de objeto ou o operando esquerdo for nulo, as operações serão nulas.
Literais de cadeia de caracteres podem conter sequências de nova linha. Você não precisa da solução alternativa antiga de usar <xml><![CDATA[...text with newlines...]]></xml>.Value
Comentários
É possível colocar comentários após continuações de linha implícitas em expressões inicializadora e entre termos de expressão LINQ.
Resolução de nome totalmente qualificado mais inteligente
Dado um código como Threading.Thread.Sleep(1000)
, o Visual Basic pesquisava o namespace "Threading", descobria que ele era ambíguo entre System.Threading e System.Windows.Threading e, então, relatava um erro. Agora, o Visual Basic considera os dois namespaces possíveis juntos. Se você mostrar a lista de conclusão, o editor do Visual Studio listará membros dos dois tipos na lista de conclusão.
Literais de data com o ano primeiro
Você pode ter literais de data no formato aaaa-mm-dd, #2015-03-17 16:10 PM#
.
Propriedades de interface readonly
Você pode implementar propriedades de interface readonly usando uma propriedade readwrite. A interface garante a funcionalidade mínima e não impede que uma classe de implementação permita que a propriedade seja definida.
Para facilitar a leitura do seu código, agora você pode usar TypeOf
com IsNot
.
#Disable Warning <ID> e #Enable Warning <ID>
É possível desabilitar e habilitar avisos específicos para regiões dentro de um arquivo de origem.
Melhorias no comentário da documentação XML
Ao escrever comentários de documento, você obtém o editor inteligente e suporte de build para validar nomes de parâmetro, tratamento adequado de crefs
(genéricos, operadores etc.), coloração e refatoração.
Definições de interfaces e módulos parciais
Além das classes e structs, você pode declarar interfaces e módulos parciais.
As diretivas #Region dentro de corpos de método
Você pode colocar delimitadores #Region...#End Region em qualquer lugar em um arquivo, dentro de funções e até mesmo estendê-los por corpos de função.
Definições de substituição são implicitamente sobrecargas
Se você adicionar o modificador Overrides
a uma definição, o compilador adicionará implicitamente Overloads
, para que você possa digitar menos código em casos comuns.
CObj permitido em argumentos de atributos
O compilador apresentava um erro de que CObj(...) não era uma constante quando usado em construções de atributo.
Declarando e consumindo métodos ambíguos de diferentes interfaces
Anteriormente, o código a seguir gerava erros que impediam você de declarar IMock
ou chamar GetDetails
(se eles tivessem sido declarados em C#):
Interface ICustomer
Sub GetDetails(x As Integer)
End Interface
Interface ITime
Sub GetDetails(x As String)
End Interface
Interface IMock : Inherits ICustomer, ITime
Overloads Sub GetDetails(x As Char)
End Interface
Interface IMock2 : Inherits ICustomer, ITime
End Interface
Agora, o compilador usará regras de resolução de sobrecarga normais para escolher o GetDetails
mais apropriado a ser chamado e você pode declarar relações de interface no Visual Basic, como aquelas mostradas no exemplo.