Novità in Visual Basic

Questo argomento elenca i nomi delle funzionalità principali per ogni versione di Visual Basic, con descrizioni dettagliate delle funzionalità nuove e migliorate nelle più recenti versioni del linguaggio.

Versione corrente

Visual Basic 16.9 / Visual Studio 2019 versione 16.9
Per nuove funzionalità, vedere Visual Basic 16.9.

È possibile scaricare l'SDK .NET più recente dalla pagina dei download .NET.

Versioni precedenti

Visual Basic 16.0 / Visual Studio 2019 versione 16.0
Per nuove funzionalità, vedere Visual Basic 16.0.

Visual Basic 15.5 / Visual Studio 2017 versione 15.5
Per nuove funzionalità, vedere Visual Basic 15.5.

Visual Basic 15.3 / Visual Studio 2017 versione 15.3
Per nuove funzionalità, vedere Visual Basic 15.3.

Visual Basic 15/Visual Studio 2017
Per nuove funzionalità, vedere Visual Basic 2017.

Visual Basic/Visual Studio 2015
Per nuove funzionalità, vedere Visual Basic 14.

Visual Basic/Visual Studio 2013
Anteprime tecnologiche del .NET Compiler Platform ("Roslyn")

Visual Basic/Visual Studio 2012
Parole chiave Async e await, iteratori, attributi relativi alle informazioni sul chiamante

Visual Basic, Visual Studio 2010
Proprietà implementate automaticamente, inizializzatori di insieme, continuazione di riga implicita, elementi dinamici, covarianza/controvarianza generica, accesso agli spazi dei nomi globali

Visual Basic/Visual Studio 2008
Language Integrated Query (LINQ), valori letterali XML, inferenza del tipo di variabile locale, inizializzatori di oggetto, tipi anonimi, metodi di estensione, inferenza del tipo var locale, espressioni lambda, operatore if, metodi parziali, tipi di valore nullable

Visual Basic/Visual Studio 2005
Tipo My e tipi di helper (accesso all'app, al computer, al file system, alla rete)

Visual Basic/Visual Studio .NET 2003
Operatori di scorrimento bit, dichiarazione di variabile del ciclo

Visual Basic/Visual Studio .NET 2002
Prima versione di Visual Basic .NET

Visual Basic 16.9

Visual Basic 16,9 consente l'utilizzo di proprietà solo init.

Visual Basic 16.0

Visual Basic 16.0 è incentrato sulla fornitura di più funzionalità del runtime Visual Basic (microsoft.visualbasic.dll) a .NET Core ed è la prima versione di Visual Basic incentrata su .NET Core. Molte parti del runtime di Visual Basic dipendono da WinForms e queste verranno aggiunte in una versione successiva di Visual Basic.

Commenti consentiti in più posizioni all'interno di istruzioni

In Visual Basic 15.8 e versioni precedenti, i commenti sono consentiti solo su righe vuote, alla fine di un'istruzione o in posizioni specifiche all'interno di un'istruzione in cui è consentita una continuazione di riga implicita. A partire da Visual Basic 16.0, i commenti sono consentiti anche dopo le continuazioni esplicite della riga e all'interno di un'istruzione che inizia con uno spazio seguito da un carattere di sottolineatura.

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

Ottimizzazione della conversione da virgola mobile a Integer

Nelle versioni precedenti di Visual Basic, le prestazioni della conversione dei valori Double e Single in valori Integer erano relativamente scarse. Visual Basic 15.8 migliora significativamente le prestazioni delle conversioni di valori da virgola mobile a Integer quando il valore restituito da uno dei metodi seguenti viene passato a una delle funzioni intrinseche di conversione di interi di Visual Basic (CByte, CShort, CInt, CLng, CSByte, CUShort, CUInt, CULng) o quando per il valore restituito da uno dei metodi seguenti viene eseguito il cast implicito a un tipo Integer e Option Strict è Off:

Questa ottimizzazione consente un'esecuzione più rapida del codice, fino a due volte più rapida nei casi di esecuzione di un numero elevato di conversioni a tipi Integer. L'esempio seguente illustra alcune semplici chiamate di metodi interessati da questa ottimizzazione:

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

Si noti che in questo caso i valori a virgola mobile vengono troncati anziché arrotondati.

Visual Basic 15.5

Argomenti denominati non finali

In Visual Basic 15.3 e versioni precedenti, quando una chiamata al metodo includeva argomenti in base alla posizione e al nome, gli argomenti posizionali dovevano precedere gli argomenti denominati. A partire da Visual Basic 15,5, gli argomenti posizionali e denominati possono trovarsi in qualsiasi ordine, purché tutti gli argomenti fino all'ultimo argomento posizionale si trovino nella posizione corretta. Ciò è particolarmente utile quando gli argomenti denominati vengono utilizzati per rendere il codice più leggibile.

Ad esempio, la seguente chiamata al metodo ha due argomenti posizionali tra un argomento denominato. L'argomento denominato chiarisce che il valore 19 rappresenta un'età.

StudentInfo.Display("Mary", age:=19, #9/21/1998#)

Private Protected modificatore di accesso ai membri

Questa nuova combinazione di parole chiave definisce un membro accessibile da tutti i membri nella classe che lo contiene, oltre che dai tipi derivati dalla classe che lo contiene, ma solo se si trovano anche nell'assembly che lo contiene. Poiché le strutture non possono essere ereditate, è possibile applicare Private Protected solo ai membri di una classe.

Separatore esadecimale/binario/ottali iniziale

Visual Basic 2017 ha aggiunto il supporto del carattere di sottolineatura (_) come separatore di cifre. A partire da Visual Basic 15.5, è possibile usare il carattere di sottolineatura come separatore iniziale tra il prefisso e la cifra esadecimale, binaria o ottale. L'esempio seguente usa il separatore di cifra iniziali per definire 3.271.948.384 come numero esadecimale:

Dim number As Integer = &H_C305_F860

Per usare il carattere di sottolineatura come separatore iniziale, è necessario aggiungere l'elemento seguente al file di progetto Visual Basic (*.vbproj):

<PropertyGroup>
  <LangVersion>15.5</LangVersion>
</PropertyGroup>

Visual Basic 15.3

Inferenza di tupla denominata

Quando si assegna il valore di elementi di tupla provenienti da variabili, Visual Basic deduce il nome degli elementi di tupla dai nomi di variabili corrispondenti; non è necessario assegnare esplicitamente un nome a un elemento di tupla. L'esempio seguente usa l'inferenza per creare una tupla con tre elementi denominati, 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

Nuove opzioni del compilatore

Il compilatore della riga di comando di Visual Basic ora supporta le opzioni -refout e -refonly per il controllo dell'output degli assembly di riferimento. -refout definisce la directory di output dell'assembly di riferimento, mentre -refonly specifica che il risultato della compilazione può essere solo un assembly di riferimento.

Visual Basic 15

Tuple

Le tuple sono una semplice struttura dei dati che viene solitamente usata per restituire più valori da una singola chiamata al metodo. In genere, per restituire più valori da un metodo, è necessario eseguire una delle operazioni seguenti:

  • Definire un tipo personalizzato (Class o Structure). Si tratta di una soluzione complicata.

  • Definire uno o più parametri ByRef e restituire un valore dal metodo.

Grazie al supporto per tuple di Visual Basic è possibile definire rapidamente una tupla, assegnare facoltativamente nomi semantici ai rispettivi valori e recuperare rapidamente i relativi valori. L'esempio seguente esegue il wrapping di una chiamata al metodo TryParse e restituisce una 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

A questo punto è possibile chiamare il metodo e gestire la tupla restituita con codice simile al seguente.

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

Valori letterali binari e separatori di cifre

È possibile definire un valore letterale binario usando il prefisso &B o &b. È anche possibile usare il carattere di sottolineatura _ come separatore di cifre per rendere il codice più leggibile. Nell'esempio seguente vengono usate entrambe le funzionalità per assegnare un valore Byte e visualizzarlo come un numero decimale, esadecimale e binario.

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)      

Per altre informazioni, vedere la sezione dedicata alle assegnazioni di valori letterali dei tipi di dati Byte, Integer, Long, Short, SByte, UInteger, ULong e UShort.

Supporto per i valori restituiti dei riferimenti C#

A partire dalla versione 7.0, C# supporta i valori di riferimento restituiti. Pertanto, quando la chiamata al metodo riceve un valore di riferimento restituito, lo può modificare. Visual Basic non consente di creare metodi con valori di riferimento restituiti, ma consente di usare e modificare tali valori.

Ad esempio, la classe Sentence seguente scritta in C# include un metodo FindNext che rileva la parola successiva in una frase che inizia con una sottostringa specificata. La stringa viene restituita come valore di riferimento restituito. Una variabile Boolean passata dal riferimento al metodo indica se la ricerca ha avuto esito positivo. Ciò significa che oltre alla lettura del valore restituito, il chiamante può anche modificarlo e che la modifica viene riflessa nella 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();
    }
}

In parole semplici, è possibile modificare la parola trovata nella frase usando un codice simile al seguente. Si noti che non si sta assegnando un valore al metodo, ma all'espressione che il metodo restituisce, ovvero il valore di riferimento restituito.

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.

Esiste tuttavia un problema con questo codice. Se non viene trovata una corrispondenza, il metodo restituisce la prima parola. L'esempio non esamina il valore dell'argomento Boolean per determinare se viene trovata una corrispondenza. Modifica quindi la prima parola se non esiste corrispondenza. Nell'esempio seguente questo problema viene risolto sostituendo la prima parola con la parola stessa se non esiste corrispondenza.

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.

Una soluzione migliore consiste nell'usare un metodo helper al quale il riferimento passa il valore di riferimento restituito. Il metodo helper può quindi modificare l'argomento passato dal riferimento. Nell'esempio seguente viene eseguita questa operazione.

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.

Per altre informazioni, vedere Riferimenti ai valori restituiti.

Visual Basic 14

NameOf

È possibile ottenere il nome di stringa non qualificato di un tipo o di un membro, da usare in un messaggio di errore senza definire una stringa a livello di codice. In questo modo il codice sarà corretto anche durante il refactoring. Questa funzionalità è utile anche per l'associazione di collegamenti MVC (Modello-Vista-Controller) e la generazione di eventi di modifica di proprietà.

Interpolazione di stringhe

È possibile usare espressioni di interpolazione di stringhe per costruire stringhe. Un'espressione di stringa interpolata è simile a una stringa di modello che contiene espressioni. In relazione agli argomenti, è più facile comprendere una stringa interpolata che la formattazione composita.

Accesso e indicizzazione dei membri condizionali Null

È possibile verificare la presenza di valori null con una sintassi molto leggera prima di eseguire un'operazione di accesso ai membri (?.) o di indice (?[]). Questi operatori consentono di scrivere meno codice per gestire i controlli null, soprattutto per l'ordinamento decrescente delle strutture di dati. Se l'operando di sinistra o il riferimento a un oggetto è null, le operazioni restituiscono null.

Valori letterali stringa a più righe

I valori letterali stringa possono contenere sequenze di nuove righe. Non è più necessario usare <xml><![CDATA[...text with newlines...]]></xml>.Value come soluzione alternativa.

Commenti

È possibile inserire commenti dopo le continuazioni di riga implicita, all'interno delle espressioni dell'inizializzatore e tra i termini delle espressioni LINQ.

Risoluzione dei nomi completa più intelligente

In precedenza, con un codice come Threading.Thread.Sleep(1000), Visual Basic cercava lo spazio dei nomi "Threading", individuava un'ambiguità tra System.Threading e System.Windows.Threading e quindi segnalava un errore. Visual Basic ora prende in considerazione entrambi gli spazi dei nomi possibili. Se si visualizza l'elenco di completamento, l'editor di Visual Studio elenca i membri di entrambi i tipi in questo elenco.

Valori letterali data anno

I valori letterali data possono avere il formato aaaa-mm-gg, #2015-03-17 16:10 PM#.

Proprietà dell'interfaccia readonly

È possibile implementare proprietà dell'interfaccia readonly usando una proprietà readonly. L'interfaccia garantisce la funzionalità minima e le classi di implementazione non smettono di consentire l'impostazione della proprietà.

Tipo TypeOf <expr> IsNot <>

Per una maggiore leggibilità del codice, ora è possibile usare TypeOf con IsNot.

ID avviso <> #Disable e ID avviso <#Enable>

È possibile disabilitare e abilitare avvisi specifici per le aree all'interno di un file di origine.

Miglioramenti dei commenti in formato documentazione XML

Quando si scrivono commenti ai documenti, si accede a Smart Editor e al supporto per la compilazione per la convalida di nomi di parametro, la corretta gestione di crefs (generics, operatori e così via), la colorazione e il refactoring.

Definizioni di interfaccia e moduli parziali

Oltre a classi e struct, è possibile dichiarare interfacce e moduli parziali.

direttive #Region all'interno dei corpi dei metodi

È possibile inserire delimitatori #Region...#End Region in qualsiasi punto di un file, nelle funzioni o nei corpi delle funzioni.

Le definizioni delle sostituzioni sono in modo implicito overload

Se si aggiunge il modificatore Overrides a una definizione, il compilatore aggiunge in modo implicito Overloads. In questo modo è possibile digitare meno codice nella maggior parte dei casi.

CObj consentito negli argomenti degli attributi

Il compilatore generava un errore indicante che CObj(...), se usato nelle costruzioni degli attributi, non era una costante.

Dichiarazione e utilizzo di metodi ambigui da interfacce diverse

In precedenza il codice seguente restituiva errori che impedivano di dichiarare IMock o di chiamare GetDetails (se questi erano stati dichiarati in 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

Ora il compilatore userà le normali regole di risoluzione dell'overload per scegliere l'oggetto GetDetails più appropriato da chiamare ed è possibile dichiarare le relazioni tre le interfacce in Visual Basic, come quelle mostrate nell'esempio.

Vedi anche