Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este artículo se enumeran los nombres de características clave para cada versión de Visual Basic. Para obtener descripciones detalladas de las características nuevas y mejoradas en las versiones más recientes del idioma, consulte las secciones vinculadas.
Versión actual
Visual Basic 17.13 / Visual Studio 2026
Para ver las nuevas características, consulte Visual Basic 17.13.
Puede descargar el SDK de .NET más reciente desde la página de descargas de .NET.
Versiones anteriores
Visual Basic 17.0 / Visual Studio 2022
Para ver las nuevas características, consulte Visual Basic 17.0.
Visual Basic 16.9 / Visual Studio 2019, versión 16.9
Para ver las nuevas características, consulte Visual Basic 16.9.
Visual Basic 16.0 / Visual Studio 2019, versión 16.0
Para ver las nuevas características, consulte Visual Basic 16.0.
Visual Basic 15.5 / Visual Studio 2017, versión 15.5
Para ver las nuevas características, consulte Visual Basic 15.5.
Visual Basic 15.3 / Visual Studio 2017, versión 15.3
Para ver las nuevas características, consulte Visual Basic 15.3.
Visual Basic 15/Visual Studio 2017
Para ver las nuevas características, consulte Visual Basic 2017.
Visual Basic/Visual Studio 2015
Para ver las nuevas características, consulte Visual Basic 14.
Visual Basic/Visual Studio 2013
Versiones preliminares de tecnología de .NET Compiler Platform ("Roslyn")
Visual Basic/Visual Studio 2012
Async y await palabras clave, iteradores, atributos de información del autor de la llamada
Visual Basic, Visual Studio 2010
Propiedades implementadas automáticamente, inicializadores de colección, continuación de línea implícita, dinámica, varianza genérica de co/contra, acceso global al espacio de nombres
Visual Basic/Visual Studio 2008
Language Integrated Query (LINQ), literales XML, inferencia de tipos locales, inicializadores de objetos, tipos anónimos, métodos de extensión, inferencia de tipos locales var , expresiones lambda, if operador, métodos parciales, tipos de valor que aceptan valores NULL
Visual Basic/Visual Studio 2005
El My tipo y los tipos auxiliares (acceso a la aplicación, el equipo, el sistema de archivos, la red)
Visual Basic/Visual Studio .NET 2003
Operadores de desplazamiento de bits, declaración de variable de bucle
Visual Basic/Visual Studio .NET 2002
La primera versión de Visual Basic .NET
Visual Basic 17.13
Visual Basic 17.13 reconoce la unmanaged restricción genérica. Visual Basic 17.13 reconoce el System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute para la resolución de métodos.
Visual Basic 17.0
Visual Basic 17.0 habilita el System.Runtime.CompilerServices.CallerArgumentExpressionAttribute.
Visual Basic 16.9
Visual Basic 16.9 permite el consumo de propiedades solo iniciales.
Visual Basic 16.0
Visual Basic 16.0 se centra en proporcionar más características de Visual Basic Runtime (microsoft.visualbasic.dll) a .NET Core. Es la primera versión de Visual Basic centrada en .NET Core. .NET Core 3.0 agrega las partes del entorno de ejecución de Visual Basic que dependen de Windows Forms.
Comentarios permitidos en más lugares dentro de instrucciones
En Visual Basic 15.5 y versiones anteriores, solo puede agregar comentarios en líneas en blanco, al final de una instrucción o en lugares específicos dentro de una instrucción donde se permite una continuación de línea implícita. A partir de Visual Basic 16.0, también puede agregar comentarios después de las continuaciones de línea explícitas y dentro de una instrucción en una línea que comienza con un espacio seguido de un carácter de subrayado.
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
Conversión optimizada de punto flotante a entero
En versiones anteriores de Visual Basic, la conversión de valores Double y Single a enteros ofrecía un rendimiento relativamente deficiente. Visual Basic 16.0 mejora significativamente el rendimiento de las conversiones de números de punto flotante a enteros cuando se pasa el valor devuelto por cualquiera de los métodos siguientes a una de las funciones intrínsecas de conversión de enteros de Visual Basic (CByte, CShort, CInt, CLng, CSByte, CUShort, CUInt y CULng), o cuando el valor devuelto por cualquiera de los métodos siguientes se convierte implícitamente en un tipo integral y Option Strict se establece en 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)
Esta optimización permite que el código se ejecute más rápido, hasta dos veces más rápido para el código que realiza un gran número de conversiones a tipos enteros. En el ejemplo siguiente se muestran algunas llamadas de método simples a las que afecta la optimización:
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
Esta optimización trunca en lugar de redondear valores de punto flotante.
Visual Basic 15.5
Argumentos con nombre no finales
En Visual Basic 15.3 y versiones anteriores, cuando una llamada al método incluía argumentos por posición y por nombre, tenía que colocar argumentos posicionales antes de los argumentos con nombre. A partir de Visual Basic 15.5, puede mezclar argumentos posicionales y con nombre en cualquier orden siempre que todos los argumentos hasta el último argumento posicional estén en la posición correcta. Esta flexibilidad es especialmente útil cuando los argumentos con nombre hacen que el código sea más legible.
Por ejemplo, la siguiente llamada al método tiene dos argumentos posicionales entre un argumento con nombre. El argumento con nombre deja claro que el valor 19 representa una edad.
StudentInfo.Display("Mary", age:=19, #9/21/1998#)
Private Protected modificador de acceso de miembro
Esta nueva combinación de palabras clave define un miembro al que pueden tener acceso todos los miembros de su clase contenedora, así como los tipos derivados de la clase contenedora, pero solo si también se encuentran en el ensamblado contenedor. Dado que las estructuras no se pueden heredar, solo se pueden aplicar Private Protected a los miembros de una clase.
Separador hexadecimal/ binario/octal inicial
Visual Basic 2017 agregó compatibilidad con el carácter de subrayado (_) como separador de dígitos. A partir de Visual Basic 15.5, puede usar el carácter de subrayado como separador inicial entre el prefijo y los dígitos hexadecimales, binarios o octales. En el ejemplo siguiente se usa un separador de dígitos inicial para definir 3.271.948.384 como un número hexadecimal:
Dim number As Integer = &H_C305_F860
Para usar el carácter de subrayado como separador inicial, debe agregar el siguiente elemento al archivo del proyecto de Visual Basic (*.vbproj):
<PropertyGroup>
<LangVersion>15.5</LangVersion>
</PropertyGroup>
Visual Basic 15.3
Inferencia de tupla con nombre
Al asignar a los elementos de la tupla los valores de las variables, Visual Basic deduce el nombre de los elementos de la tupla a partir de los nombres correspondientes de las variables. No es necesario asignar un nombre explícito a un elemento de tupla. En el ejemplo siguiente se usa la inferencia para crear una tupla con dos elementos con nombre: state y stateName.
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
Modificadores de compilador adicionales
El compilador de línea de comandos de Visual Basic ahora admite las opciones del compilador -refout y -refonly para controlar la salida de los ensamblados de referencia. Use -refout para definir el directorio de salida del ensamblado de referencia. Use -refonly para especificar que la compilación genera solo un ensamblado de referencia.
Visual Basic 15
Las tuplas son una estructura de datos ligera que se usa normalmente para devolver varios valores desde una sola llamada de método. Normalmente, para devolver varios valores de un método, debe realizar una de las siguientes opciones:
Defina un tipo personalizado (o
Class).StructureEsta opción es una solución robusta.Defina uno o varios
ByRefparámetros, además de devolver un valor del método .
La compatibilidad de Visual Basic con tuplas le permite definir rápidamente una tupla, asignar opcionalmente nombres semánticos a sus valores y recuperar rápidamente sus valores. En el ejemplo siguiente se ajusta una llamada al TryParse método y se devuelve 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 continuación, puede llamar al método y gestionar la tupla devuelta utilizando un código como el siguiente ejemplo.
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
Literales binarios y separadores de dígitos
Puede definir un literal binario mediante el prefijo &B o &b. Además, puede usar el carácter de subrayado, _, como separador de dígitos para mejorar la legibilidad. En el ejemplo siguiente se usan ambas características para asignar un Byte valor y mostrarlo como un número decimal, hexadecimal y 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)
Para obtener más información, vea la sección "Asignaciones literales" de los tipos de datos Byte, Integer, Long, Short, SByte, UInteger, ULong y UShort .
Compatibilidad con valores devueltos de referencia de C#
C# admite valores devueltos de referencia. Es decir, cuando el método de llamada recibe un valor devuelto por referencia, puede cambiar el valor de la referencia. Visual Basic no permite crear métodos con valores devueltos de referencia, pero permite consumir y modificar los valores devueltos de referencia.
Por ejemplo, la siguiente Sentence clase escrita en C# incluye un FindNext método que encuentra la siguiente palabra en una oración que comienza con una subcadena especificada. La cadena se devuelve como un valor devuelto de referencia y una Boolean variable pasada por referencia al método indica si la búsqueda se realizó correctamente. Esto significa que, además de leer el valor devuelto, el autor de la llamada también puede modificarlo y esa modificación se refleja en la Sentence clase .
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();
}
}
En su forma más sencilla, puede modificar la palabra que se encuentra en la oración mediante código como el ejemplo siguiente. Tenga en cuenta que no va a asignar un valor al método, sino a la expresión que devuelve el método, que es el valor devuelto de referencia.
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.
Sin embargo, un problema con este código es que, si no se encuentra una coincidencia, el método devuelve la primera palabra. Dado que el ejemplo no examina el valor del Boolean argumento para determinar si se encuentra una coincidencia, modifica la primera palabra si no hay ninguna coincidencia. En el ejemplo siguiente se corrige este problema reemplazando la primera palabra por sí misma si no hay ninguna coincidencia.
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 mejor solución consiste en usar un método auxiliar al que se pasa el valor devuelto de referencia por referencia. A continuación, el método auxiliar puede modificar el argumento que se le pasa por referencia. En el ejemplo siguiente se hace eso.
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 obtener más información, vea Valores devueltos de referencia.
Visual Basic 14
Puede obtener el nombre de cadena no calificado de un tipo o miembro para usarlo en un mensaje de error sin codificar una cadena de forma rígida. Este enfoque mantiene el código correcto al refactorizar. Esta característica también es útil para enlazar vínculos MVC del controlador de vista del modelo y desencadenar eventos modificados de propiedades.
Use expresiones de interpolación de cadenas para construir cadenas. Una expresión de cadena interpolada es similar a una cadena de plantilla que contiene expresiones. Una cadena interpolada es más fácil de entender con respecto a los argumentos que el formato compuesto.
Acceso y indexación de miembros condicionales NULL
Puede probar null de una manera sintáctica muy ligera antes de realizar una operación de acceso a miembros (?.) o índice (?[]). Estos operadores le ayudan a escribir menos código para controlar comprobaciones nulas, especialmente para descendentes en estructuras de datos. Si el operando izquierdo o la referencia de objeto es NULL, las operaciones devuelven null.
Literales de cadena de varias líneas
Los literales de cadena pueden contener secuencias de nueva línea. Ya no necesita la antigua solución alternativa de usar <xml><![CDATA[...text with newlines...]]></xml>.Value.
Comentarios
Puede colocar comentarios después de las continuaciones de línea implícitas, dentro de las expresiones del inicializador y entre los términos de expresión LINQ.
Resolución de nombres completa más inteligente
Dado el código como Threading.Thread.Sleep(1000), Visual Basic solía buscar en el espacio de nombres "Threading", detectar que era ambiguo entre System.Threading y System.Windows.Threading, y a continuación, notificar un error. Visual Basic ahora considera ambos posibles espacios de nombres juntos. Si muestra la lista de finalización, el editor de Visual Studio enumera los miembros de ambos tipos en la lista de finalización.
Literales de fecha de año
Puede tener literales de fecha en formato aaaa-mm-dd, #2015-03-17 16:10 PM#.
Propiedades de la interfaz readonly
Puede implementar propiedades de interfaz de solo lectura mediante una propiedad readwrite. La interfaz garantiza una funcionalidad mínima y no impide que una clase de implementación permita establecer la propiedad.
Para obtener más legibilidad del código, ahora puede usar TypeOf con IsNot.
id.< de advertencia >de #Disable y id. de advertencia <de #Enable>
Puede deshabilitar y habilitar advertencias específicas para regiones dentro de un archivo de origen.
Mejoras en los comentarios de documentos XML
Al escribir comentarios de documentos, obtendrá compatibilidad con el editor inteligente para la validación de nombres de parámetros, el manejo adecuado de crefs (por ejemplo, genéricos y operadores), el colorizado y la refactorización.
Definiciones parciales de módulo e interfaz
Además de las clases y estructuras, puede declarar módulos e interfaces parciales.
#Region directivas dentro de los cuerpos del método
Puede colocar #Region...#End delimitadores de región en cualquier lugar de un archivo, dentro de funciones e incluso abarcar entre cuerpos de función.
Las definiciones de invalidaciones son sobrecargas implícitas
Si agrega el Overrides modificador a una definición, el compilador agrega Overloads implícitamente para que pueda escribir menos código en casos comunes.
CObj permitido en los argumentos de atributos
Ahora puede usar CObj(...) en argumentos de atributo. Anteriormente, el compilador devolvía un error que indica que no era una constante.
Declarar y consumir métodos ambiguos de diferentes interfaces
Anteriormente, el código siguiente devolvía errores que le impedían declarar IMock o llamar a GetDetails (si estos métodos se declararon en 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
Ahora, el compilador usa reglas de resolución de sobrecarga normales para elegir el método más adecuado GetDetails al que llamar. Puede declarar relaciones de interfaz en Visual Basic como las que se muestran en el ejemplo.