Desde el nacimiento del lenguaje Visual Basic en 1991, ha sido una herramienta muy eficiente para crear aplicaciones. Casi 20 años después, continúa brindando una fácil integración con Microsoft .NET Framework, lo que permite a los desarrolladores escribir aplicaciones que abarcan computadoras de escritorio, teléfonos, navegadores e incluso la nube.
Microsoft lanzará Visual Studio 2010 este mes, que incluye Visual Basic versión 10 (a veces llamado VB 2010 o VB10). Esta versión es la más potente hasta el momento e incluye muchas funciones que ahorran tiempo y ayudan a los desarrolladores a hacer más con menos líneas de código. Aquí se le proporcionará todo el contenido necesario para comprender y aprovechar Visual Basic en Visual Studio 2010.
coevolución
En el pasado, Visual Basic y C# eran desarrollados por equipos separados, lo que a menudo daba como resultado que las características aparecieran primero en un lenguaje y luego en el otro. Por ejemplo, C# tiene propiedades implementadas automáticamente e inicializadores de colección que no están disponibles en Visual Basic, y Visual Basic tiene características como enlace tardío y parámetros opcionales que no están disponibles en C#. Pero cada vez que un idioma obtiene una nueva característica, muchos clientes solicitan que esa característica también se agregue al otro idioma.
Para abordar esta necesidad, Microsoft fusionó los equipos de Visual Basic y C# para implementar una estrategia de coevolución. El objetivo es promover el desarrollo común de estas lenguas. Cuando se introduce una característica importante en un idioma, también aparece en el otro idioma. Eso no quiere decir que todas las características estarán presentes en ambos idiomas y funcionarán exactamente de la misma manera; de hecho, cada idioma tiene su propia historia, alma y sentimiento, y es importante preservar estas características;
En .NET Framework 4, Visual Basic y C# dieron un gran paso hacia este objetivo, cada uno absorbiendo muchas de las características existentes del otro. Sin embargo, la coevolución no sólo afecta a la funcionalidad anterior sino que también es una estrategia para el desarrollo futuro de estos lenguajes. Con este espíritu, .NET Framework 4 introduce potentes características nuevas en ambos lenguajes, como el tiempo de ejecución del lenguaje dinámico, tipos de interoperabilidad integrados y variaciones genéricas, lo que permite a los desarrolladores de Visual Basic y C# aprovechar al máximo .NET Framework.
Novedades de Visual Basic 2010
Las nuevas funciones de Visual Basic 2010 están diseñadas para ayudarle a hacer más con menos líneas de código. Nuestro equipo de diseño de Visual Basic examinó de cerca los lugares donde los desarrolladores normalmente tienen que escribir una gran cantidad de código repetitivo tedioso y encontró formas de dejar que el compilador haga el trabajo. Por supuesto, esta es una visión general, ahora echemos un vistazo más profundo a cada característica.
Carácter de continuación de línea implícito
Visual Basic es un lenguaje orientado a líneas que utiliza una sintaxis clara similar al inglés para mejorar la legibilidad. Pero esto a menudo da como resultado que el código alcance el límite de 80 caracteres por línea, lo que obliga a los desarrolladores a desplazarse mucho. Puede utilizar el carácter de subrayado para indicarle al compilador que el procesamiento de la siguiente línea debe continuar como la línea actual (es decir, tratar varias líneas físicas como una sola línea lógica). Pero tener que escribir el carácter de subrayado repetidamente ha sido molesto y, de hecho, una de las principales solicitudes de funciones durante años fue que el compilador solucionara este problema.
En Visual Basic 2010, el compilador puede solucionar este problema. El compilador ahora sabe qué tokens (como comas, paréntesis y operadores) tienden a aparecer antes de los caracteres de continuación de línea e inserta caracteres para que los desarrolladores ya no necesiten insertarlos. Por ejemplo, ciertamente no es lógico terminar una declaración de Visual Basic con una coma; el compilador lo sabe, por lo que cuando ve una secuencia de tokens como {coma, enter}, infiere la presencia de un carácter de continuación de línea, como se muestra en la Figura. Se muestra el ejemplo en 1.
Figura 1 Inferir caracteres de continuación de línea
<Extension()>
Función FiltrarPorPaís(
Clientes de ByVal como IEnumerable (del cliente),
País ByVal como cadena) como IEnumerable (del cliente)
Consulta oscura =
De c En clientes
Donde c.País = país
Seleccione <Cliente>
<%=
c.Nombre &
, &
c.País
%>
</Cliente>
Consulta de devolución
Función final
En Visual Basic 2008, el código de la Figura 1 requeriría 9 caracteres de subrayado. Sin embargo, en cada uno de los siguientes casos, el compilador infiere cuándo es necesario el carácter de subrayado y permite ignorarlo:
Después del atributo <Extensión()>
después ((paréntesis izquierdo) en la declaración del método
después de , (coma) del primer parámetro
antes) (paréntesis derecho) en la declaración del método
después = (signo igual)
después de <%= (la etiqueta de apertura de una expresión incrustada)
Después de cada signo (ampersand) en texto XML
antes de %> (etiqueta final de la expresión incrustada)
Esta nueva característica del compilador es particularmente útil para firmas de métodos, que también funcionarán bien para más de 80 caracteres en el ejemplo mostrado (si cada parte está en la misma línea). En la Figura 2, verá todas las combinaciones de etiquetas y posiciones para las cuales están implícitos caracteres de continuación de línea.
Figura 2 Cuando el carácter de continuación de línea está implícito
marca | Antes | después |
, (coma), . (punto), > (atributo), ( { (corchete izquierdo), <%= (etiqueta de inicio de expresión incrustada (texto XML)) | incógnita | |
), }, ] (corchete derecho), %> (etiqueta final de expresión incrustada) | incógnita | |
Todas las palabras clave de LINQ: Agregar, Distinto, De, Agrupar por, Unirse al grupo, Unirse, Dejar, Ordenar por, Seleccionar, Omitir, Omitir mientras, Tomar, Tomar mientras, Dónde, En, Dentro, En, Ascendente, Descendente | incógnita | incógnita |
Operador: +, -,*,/,/,^,>>,<<,Mod,&,+=,-=,*=,/=,/=,^=,>>=,<<=, & =, <, <=, >, >=, <>, es, no es, como, y, o, xor, y también, o si no | incógnita | |
Con (en inicializador de objetos) | incógnita |
Como puede ver, hay más de 60 lugares en el idioma donde no se requiere el carácter de subrayado. (De hecho, ninguno de los ejemplos de código de este artículo requiere caracteres de continuación de línea). Por supuesto, aún puede usar el carácter de subrayado, por lo que el código de versiones anteriores de Visual Basic aún se compilará como se esperaba.
DeclaraciónLambda
El término lambda puede parecer aterrador al principio, pero una lambda es solo una función definida dentro de otra función. Visual Basic 2008 introdujo expresiones lambda con la palabra clave Función:
Dim customers As Customer() = ...
Array.FindAll(clientes, Función(c) c.País = Canadá)
Las expresiones Lambda le permiten expresar la lógica localmente de forma granular y compacta sin tener que dividirla en varios métodos. Por ejemplo, aquí está la representación del código anterior en Visual Basic 2005 (que no admite expresiones lambda):
Dim query = Array.FindAll(customers, AddressOf Filter)
...
Filtro de función (ByVal c como cliente) como booleano
Volver c.País = Canadá
Función final
Desafortunadamente, las expresiones lambda de Visual Basic 2008 requieren que la expresión devuelva un valor, por lo que el siguiente código:
Array.ForEach(customers, Function(c) Console.WriteLine(c.Country))
Conducirá a la siguiente situación:
'Compile error: Expression does not produce a value.
Console.WriteLine es un procedimiento Sub (nulo en C#), por lo que no devuelve un valor, razón por la cual el compilador genera un error. Para manejar esta situación, Visual Basic 2010 introdujo soporte para declaraciones lambdas, que son lambdas que contienen una o más declaraciones:
Array.ForEach(customers, Sub(c) Console.WriteLine(c.Country))
Dado que Console.WriteLine no devuelve un valor, podemos simplemente crear una Sub lambda en lugar de una Función lambda. Aquí hay otro ejemplo que utiliza varias declaraciones:
Array.ForEach(customers, Sub(c)
Console.WriteLine(Nombre del país:)
Consola.WriteLine(c.País)
Fin Sub)
Cuando se ejecuta este código, imprime dos líneas para cada cliente. También tenga en cuenta que si pasa el cursor sobre c mientras codifica, verá que el compilador inferirá el tipo como Cliente (también es legal escribir c como Cliente para declarar explícitamente el tipo). Escribir dinámicamente controladores de eventos es otro gran uso de las declaraciones lambdas:
AddHandler b.Click, Sub(sender As Object, e As EventArgs)
MsgBox (botón hecho clic)
'inserte una lógica más compleja aquí
Subtítulo final
Y, de hecho, puede utilizar declaraciones lambdas con una característica introducida en Visual Basic 2008: delegación flexible. (Puede utilizar delegados (punteros de función con seguridad de tipos) para ejecutar varias funciones a la vez). Esta combinación da como resultado una firma mucho más simple:
AddHandler b.Click, Sub()
MsgBox (botón hecho clic)
'inserte una lógica más compleja aquí
Subtítulo final
La flexibilidad delegada le permite ignorar por completo los parámetros en los controladores de eventos; esta es una buena ventaja, siempre y cuando no se utilicen en absoluto, por lo que solo son visualmente intrusivos.
Además de las Sub lambdas de una sola línea y las Sub lambdas de varias líneas que hemos visto hasta ahora, Visual Basic 2010 también admite lambdas de función de varias líneas:
Dim query = customers.Where(Function(c)
'Devolver solo clientes que no han sido guardados
'inserte una lógica más compleja aquí
Devolver c.ID = -1
Función final)
Otro aspecto interesante de las declaraciones lambdas es cómo se cruzan con los delegados anónimos introducidos en Visual Basic 2008. La gente suele confundir a estos delegados con los métodos anónimos de C#, aunque no son estrictamente lo mismo. La delegación anónima ocurre cuando el compilador de Visual Basic infiere el tipo de delegado basándose en la firma del método lambda:
Dim method = Function(product As String)
Si producto = Papel Entonces
Devolver unidades de 4,5' en stock
Demás
Devuelve el 10'10 de todo lo demás
Terminar si
Función final
MsgBox(método(Papel))
Si ejecuta este código, verá el valor 4.5 mostrado en el cuadro de mensaje. Además, si pasa el cursor sobre el método, verá el texto Método atenuado como <Función (cadena) como doble>. Como no proporcionamos un tipo de delegado real, el compilador generará uno automáticamente de la siguiente manera:
Delegate Function $compilerGeneratedName$(product As String) As Double
Esto se denomina delegado anónimo porque sólo aparecerá en el código generado por el compilador, no en el código tal como está escrito. Tenga en cuenta que cuando en realidad no se proporciona ninguna cláusula As para especificar el tipo de retorno de lambda, el compilador infiere que el tipo de retorno es Doble. El compilador examinará todas las declaraciones de retorno dentro de lambda y determinará los tipos Doble (4.5) e Integer (10):
'Notice the As Single
Método tenue = Función (producto como cadena) como único
Si producto = Papel Entonces
Devolver unidades de 4,5' en stock
Demás
Devuelve el 10'10 de todo lo demás
Terminar si
Función final
Luego ejecuta su algoritmo de tipo de referencia y determina que puede convertir de forma segura 10 en un Doble, pero no puede convertir de manera segura 4,5 en un Entero, por lo que Doble es la mejor opción;
También puede controlar explícitamente el tipo de retorno, en cuyo caso el compilador no intentará inferir el tipo. Es muy común asignar lambda a una variable con un tipo de delegado explícito, en lugar de depender del compilador para inferir el tipo de delegado:
Dim method As Func(Of String, Single) =
Función (producto)
Si producto = Papel Entonces
Devolver unidades de 4,5' en stock
Demás
Devuelve el 10'10 de todo lo demás
Terminar si
Función final
Debido a que se proporciona un tipo de destino explícito, no es necesario declararlo como String o As Single; el compilador puede inferir su existencia basándose en el tipo de delegado en el lado izquierdo de la declaración. Entonces, si pasa el cursor sobre el producto, verá que el tipo inferido es Cadena. Ya no es necesario especificar Como único porque el tipo de delegado ya proporciona esa información. En el ejemplo anterior, la firma del delegado Func (que se incluye con .NET Framework) tiene este aspecto:
Delegate Function Func(Of T, R)(ByVal param As T) As R
Hay una pequeña excepción, como veremos más adelante en la sección sobre Variación genérica.
Propiedades implementadas automáticamente
En Visual Basic, las propiedades son miembros de una clase que exponen el estado de un objeto al mundo exterior. Una declaración de propiedad típica se parece a la siguiente:
Private _Country As String
País de propiedad como cadena
Conseguir
País_regreso
Fin de obtención
Establecer (valor ByVal como cadena)
_País = valor
Conjunto final
Propiedad final
Un concepto realmente muy simple con 10 líneas de código. Dado que un objeto típico a menudo tiene docenas de propiedades, terminas incluyendo una gran cantidad de código repetitivo en tu definición de clase. Para simplificar dichas tareas, Visual Basic 2010 introduce propiedades autoimplementadas, que le permiten definir propiedades simples con solo una línea de código:
Property Country As String
En este caso, el compilador continuará ejecutándose y generará automáticamente captadores, definidores y campos de soporte. El nombre de un campo admitido es siempre el nombre de un atributo precedido por un carácter de subrayado: _País en este ejemplo. Esta convención de nomenclatura garantiza la compatibilidad con la serialización binaria al cambiar propiedades implementadas automáticamente a propiedades normales. La serialización binaria seguirá funcionando siempre que los nombres de los campos de soporte sean los mismos.
Una de las cosas interesantes que puede hacer con las propiedades implementadas automáticamente es especificar un inicializador que establezca el valor predeterminado de la propiedad cuando se ejecuta el constructor. Por ejemplo, un escenario común con clases de entidad establece la clave principal en un valor como -1 para indicar que no está guardada. El código se verá así:
Property ID As Integer = -1
Cuando se ejecuta el constructor, el campo de respaldo (_ID) se establece automáticamente en el valor -1. La sintaxis del inicializador también funciona para tipos de referencia:
Property OrderList As List(Of Order) = New List(Of Order)
Como no es necesario escribir el nombre del tipo dos veces, es posible que la línea de código anterior no tenga características de Visual Basic muy obvias. La buena noticia es que existe una sintaxis más corta para declaraciones de variables regulares que es consistente con la sintaxis permitida por Visual Basic:
Property OrderList As New List(Of Order)
Incluso puedes usar esta sintaxis con un inicializador de objeto para permitir que se establezcan otras propiedades:
Property OrderList As New List(Of Order) With {.Capacity = 100}
Obviamente, para propiedades más complejas, todavía es necesaria una sintaxis extendida. Aún puede escribir Propiedad{Tab} para activar el fragmento de propiedad anterior. Alternativamente, después de escribir la primera línea de la propiedad, puede simplemente ingresar Get{Enter} y el IDE generará la propiedad de estilo antiguo:
Property Name As String
Conseguir
Fin de obtención
Establecer (valor ByVal como cadena)
Conjunto final
Propiedad final
Generalmente uno encuentra: la nueva sintaxis de propiedad es casi idéntica a la de los campos públicos, así que ¿por qué no utilizar campos públicos en su lugar? Hay varias razones:
La mayor parte de la infraestructura de enlace de datos .NET funciona en términos de propiedades en lugar de campos.
Una interfaz no puede imponer la presencia de un campo; puede imponer la presencia de un atributo.
Las propiedades brindan flexibilidad a largo plazo para cambiar las reglas comerciales. Por ejemplo, supongamos que alguien introduce la regla de que los números de teléfono deben tener 10 dígitos. Esta validación no se puede realizar si está asignada a un campo público. Cambiar campos públicos a propiedades es un cambio importante para escenarios como la serialización binaria y la reflexión.
Inicializador de colección
Una práctica común de .NET es crear una instancia de una colección y luego completarla llamando al método Add una vez para cada elemento:
Dim digits As New List(Of Integer)
dígitos.Añadir(0)
dígitos.Añadir(1)
dígitos.Añadir(2)
dígitos.Añadir(3)
dígitos.Añadir(4)
dígitos.Añadir(5)
dígitos.Añadir(6)
dígitos.Añadir(7)
dígitos.Añadir(8)
dígitos.Añadir(9)
Pero para un concepto fundamentalmente simple, hay mucha sobrecarga sintáctica. Visual Basic 2010 introdujo inicializadores de colecciones para facilitar la creación de instancias de colecciones. Para este código:
Dim digits = New List(Of Integer) From {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
El compilador generará automáticamente todas las llamadas al método Add. También puede utilizar la funcionalidad de sintaxis Como nuevo de Visual Basic:
Dim digits As New List(Of Integer) From {1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
Tenga en cuenta que en el equipo de Visual Basic siempre recomendamos usar la segunda sintaxis (Como nueva) en lugar de la anterior porque hace que el código sea más resistente a los cambios en la configuración de Option Infer.
Puede utilizar un inicializador de colección con cualquier tipo que cumpla los siguientes requisitos:
Puede iterar sobre el tipo utilizando una declaración For Each, es decir, el tipo implementa IEnumerable. (Para obtener una definición más precisa/detallada de los tipos de colección, consulte la Sección 10.9.3 de la Especificación del lenguaje Visual Basic en msdn.microsoft.com/library/aa711986(VS.71).aspx).
El tipo tiene un constructor sin parámetros accesible (pero no necesariamente público).
El tipo tiene una instancia accesible (pero no necesariamente pública) o un método de extensión denominado Agregar.
Esto significa que también puedes usar inicializadores de colección para tipos más complejos, como diccionarios:
Dim lookupTable As New Dictionary(Of Integer, String) From
{{1, uno},
{2, dos},
{3, tres},
{4, cuatro}}
(Tenga en cuenta que, aunque esta declaración abarca cinco líneas, no hay caracteres de subrayado). En este caso, el compilador generará un código equivalente a la forma antigua de inicializar un diccionario:
Dim lookupTable As New Dictionary(Of Integer, String)
lookupTable.Add(1, Uno)
lookupTable.Add(2, dos)
lookupTable.Add(3, Tres)
lookupTable.Add(4, Cuatro)
El compilador llama al método Add con dos parámetros en lugar de uno. Sabe hacer esto porque el valor pasado al inicializador de la colección está dentro de llaves anidadas, como esta: {{1, Uno}, {2, Dos},…}. Para cada conjunto de llaves anidadas, el compilador intenta pasar estos parámetros a un método Add compatible.
También es posible proporcionar su propia implementación Add personalizada mediante el uso de métodos de extensión:
<Extension()>
Sub Agregar (fuente ByVal como IList (del cliente),
ByVal id como número entero,
Nombre de ByVal como cadena,
ByVal ciudad como cadena)
source.Add(Nuevo cliente con
{
.ID = identificación,
.Nombre = nombre,
.Ciudad = ciudad
})
Subtítulo final
(¡Mire todos esos caracteres de subrayado que faltan!) Este método extiende cualquier tipo que implemente IList(Of Customer), lo que luego le permite usar la nueva sintaxis del inicializador de colección, como esta:
Dim list = New List(Of Customer) From
{
{1, Jon, Redmond},
{2, Bob, Seattle},
{3, Sally, Toronto}
}
(Agregue tres clientes a la lista). También puede utilizar inicializadores de colección con propiedades implementadas automáticamente:
Property States As New List(Of String) From {AL, AK, AR, AZ, ...}
literal de matriz
Además de formas más potentes de trabajar con tipos de colecciones, Visual Basic 2010 también proporciona algunas mejoras potentes para trabajar con matrices. Suponga el siguiente código (funciona bien en versiones anteriores):
Dim numbers As Integer() = New Integer() {1, 2, 3, 4, 5}
Al observar los elementos de esta matriz, es obvio que cada elemento es un número entero, por lo que tener que imprimir el número entero dos veces en esta línea realmente no agrega ningún valor. Los literales de matriz le permiten crear una matriz colocando todos los elementos de una matriz entre llaves y permitiendo que el compilador infiera automáticamente los tipos:
Dim numbers = {1, 2, 3, 4, 5}
El tipo de números no es Objeto sino Integer() (siempre que la opción Infer esté habilitada), la razón es que el literal de matriz ahora se representa a sí mismo y tiene su propio tipo. Supongamos un ejemplo más complejo:
Dim numbers = {1, 2, 3, 4, 5.555}
En este caso, el tipo de números se inferirá como Doble(). El compilador determina el tipo examinando cada elemento de la matriz y calculando el tipo base, utilizando el mismo algoritmo analizado anteriormente para inferir el tipo de retorno de una declaración lambda. ¿Qué pasa si no hay un tipo base? Por ejemplo, como se muestra en el siguiente código:
Dim numbers = {1, 2, 3, 4, 5}
En este caso, convertir un número entero en una cadena reducirá el rango de conversión (es decir, puede producirse una pérdida de datos en tiempo de ejecución) y, de manera similar, convertir una cadena en un número entero también reducirá el rango de conversión. El único tipo seguro para elegir es Object() (el compilador generará un error si Option Strict está habilitado).
Los literales de matriz se pueden anidar para formar matrices multidimensionales o matrices irregulares:
'2-dimensional array
Matriz tenue = {{1, 0}, {0, 1}}
'matriz irregular: los paréntesis fuerzan la evaluación de la matriz interna primero
Tenue irregular = { ({1, 0}), ({0, 1}) }
tiempo de ejecución del lenguaje dinámico
Aunque Visual Basic es técnicamente un lenguaje estático por naturaleza, siempre ha tenido características dinámicas muy poderosas, como el enlace tardío. Visual Studio 2010 viene con una nueva plataforma llamada Dynamic Language Runtime (DLR) que facilita la creación de lenguajes dinámicos y la comunicación entre ellos. Visual Basic 2010 se actualizó para admitir completamente DLR en sus carpetas recientes, lo que permite a los desarrolladores usar bibliotecas y marcos desarrollados en otros lenguajes (como IronPython/IronRuby).
Una de las mejores cosas de esta característica es que sintácticamente nada ha cambiado (de hecho, no se ha modificado ni una sola línea de código en el compilador para admitir esta característica). Los desarrolladores aún pueden realizar operaciones de enlace tardío como lo hacían en versiones anteriores de Visual Basic. Lo que ha cambiado es el código en el tiempo de ejecución de Visual Basic (Microsoft.VisualBasic.dll), que ahora reconoce la interfaz IDynamicMetaObjectProvider proporcionada por el DLR. Si un objeto implementa esta interfaz, el tiempo de ejecución de Visual Basic crea un DLR CallSite y permite que el objeto y el lenguaje que lo proporciona inyecten su propia semántica en la operación.
Por ejemplo, la biblioteca estándar de Python contiene un archivo llamado random.py, que tiene un método llamado shuffle que puede usarse para reorganizar aleatoriamente los elementos de una matriz. Llamar a este método es simple:
Dim python As ScriptRuntime = Python.CreateRuntime()
Dim aleatorio como objeto = python.UseFile(random.py)
Elementos oscuros = {1, 2, 3, 4, 5, 6, 7}
aleatorio.shuffle(elementos)
En tiempo de ejecución, Visual Basic ve que el objeto implementa IDynamicMetaObjectProvider y, por lo tanto, pasa el control al DLR, que luego se comunica con Python y ejecuta el método (pasando la matriz definida en Visual Basic como parámetro del método).
Este es un ejemplo de cómo llamar a una API habilitada para DLR, pero los desarrolladores también pueden crear sus propias API que utilicen esta funcionalidad. La clave es implementar la interfaz IDynamicMetaObjectProvider, en cuyo caso los compiladores de Visual Basic y C# reconocerán objetos con una semántica dinámica especial. No implemente esta interfaz manualmente, es más fácil heredar de la clase System.Dynamic.DynamicObject (que ya implementa esta interfaz) y anular solo algunos métodos. La Figura 3 muestra un ejemplo completo de cómo crear un objeto dinámico personalizado (una bolsa de propiedades que parece crear propiedades sobre la marcha) y cómo usar el enlace tardío normal de Visual Basic para llamar al objeto. (Para obtener más información sobre el uso de DynamicObject, lea el excelente artículo de Doug Rothaus en blogs.msdn.com/vbteam/archive/2010/01/20/fun-with-dynamic-objects-doug-rothaus.aspx).
Figura 3 Cree un objeto dinámico personalizado y llame al objeto mediante el enlace tardío de Visual Basic
Imports System.Dynamic
Módulo Módulo1
Subprincipal()
Dim p como objeto = Nuevo PropertyBag
p.Uno = 1
p.Dos = 2
p.Tres = 3
Consola.WriteLine(p.Uno)
Console.WriteLine(p.Dos)
Console.WriteLine(p.Tres)
Subtítulo final
Class PropertyBag: hereda DynamicObject
Valores privados como nuevo diccionario (de cadena, entero)
Función de anulación pública TrySetMember(
Carpeta ByVal como SetMemberBinder,
Valor ByVal como objeto) como booleano
valores(carpeta.Nombre) = valor
Devolver verdadero
Función final
Función de anulación pública TryGetMember(
Carpeta ByVal como GetMemberBinder,
Resultado ByRef como objeto) como booleano
Valores de retorno.TryGetValue(carpeta.Nombre, resultado)
Función final
Fin de clase
Módulo final
variación genérica
Esta es una función que puede parecer compleja al principio (con términos como covarianza y contravarianza), pero en realidad es bastante simple. Si tiene un objeto de tipo IEnumerable(Of Apple) y desea asignarlo a IEnumerable(Of Fruit), esto debería ser legal porque cada manzana es una fruta (aplicada por herencia). Desafortunadamente, antes de Visual Basic 2010, la variación genérica no era compatible con el compilador, aunque en realidad sí era compatible con Common Language Runtime (CLR).
Veamos el ejemplo de la Figura 4. En Visual Basic 2008, el código de la Figura 4 producirá un error de compilación en la línea Dim enableOnly (o, si Option Strict está deshabilitado, una excepción de tiempo de ejecución). La solución es llamar al método de extensión .Cast de la siguiente manera:
'Old way, the call to Cast(Of Control) is no longer necessary in VB 2010
Dim enableOnly = FilterEnabledOnly (botones.Cast (de control))
Esto ya no es necesario porque en Visual Basic 2010, la interfaz IEnumerable se marcó como covariante mediante el modificador Out:
Interface IEnumerable(Of Out T)
...
Interfaz final
Figura 4 Ejemplo de varianza genérica
Option Strict On
Formulario de clase pública1
Sub Form1_Load() maneja MyBase.Load
Botones atenuados como nueva lista (de botones) desde
{
Nuevo botón con
{
.Nombre = btnOk,
.Habilitado = Verdadero
},
Nuevo botón con
{
.Nombre = btnCancelar,
.Habilitado = Falso
}
}
Dim enableOnly = FilterEnabledOnly (botones)
Subtítulo final
Función FilterEnabledOnly(
Controles ByVal como IEnumerable (de control)
) Como IEnumerable(De Control)
Regresar desde c En controles
Donde c.Enabled = Verdadero
Función final
Fin de clase
Esto significa que el parámetro genérico T ahora es una variable (es decir, es adecuado para herencia) y el compilador se asegurará de que el parámetro solo se use cuando el tipo proviene de una interfaz. Los parámetros genéricos también pueden ser variables inversas, lo que significa que sólo se utilizan donde se ingresan. En realidad, un tipo puede tener ambos. Por ejemplo, el delegado Func analizado anteriormente tiene parámetros contravariantes (para lo que se pasa) y parámetros covariantes (para el tipo de retorno):
Delegate Function Func(Of In T, Out R)(ByVal param As T) As R
Puede utilizar modificadores de entrada y salida en interfaces y delegados personalizados. Muchas interfaces y delegados comunes en .NET Framework 4 están marcados como variables; los ejemplos comunes incluyen todos los delegados de Acción/Función, IEnumerable(Of T), IComparer(Of T), IQueryable(Of T), etc.
Lo mejor de la variación genérica es que es una característica de la que no tienes que preocuparte en absoluto: si está haciendo su trabajo, nunca lo notarás. Las situaciones que alguna vez resultaron en errores del compilador o requirieron llamar a .Cast(Of T) funcionan bien en Visual Basic 2010.
Parámetros opcionales mejorados
Los parámetros opcionales proporcionan una característica útil de eficiencia que permite a los desarrolladores crear métodos más flexibles y evitar saturar una clase con muchas sobrecargas de métodos. En el pasado había una ligera restricción de que los parámetros opcionales no podían ser nulos (o incluso de cualquier tipo de estructura no interna). Visual Basic 2010 ahora le permite definir parámetros opcionales de cualquier tipo de valor:
Sub DisplayOrder(ByVal customer As Customer,
ByVal ID de pedido como número entero,
Unidades ByVal opcionales ¿Como entero = 0,
Opcional ByVal backgroundColor como color = Nada)
Subtítulo final
En este ejemplo, las unidades son de tipo Nullable(Of Integer) y backgroundColor es un tipo de estructura sin contenido, pero aún se usan como parámetros opcionales. Visual Basic 2010 también proporciona un mejor soporte para parámetros opcionales genéricos.
Tipos de interoperabilidad integrados
Una debilidad común de las aplicaciones que realizan interoperabilidad COM es la necesidad de utilizar un ensamblaje de interoperabilidad primaria (PIA). Un PIA es un ensamblado .NET que actúa como un contenedor invocable en tiempo de ejecución (RCW) en un componente COM y tiene un GUID único que lo identifica. El ensamblado .NET se comunica con PIA, que luego realiza cualquier cálculo necesario para mover datos entre COM y .NET.
Desafortunadamente, los PIA pueden complicar la implementación porque son archivos DLL adicionales que deben implementarse en las computadoras de los usuarios finales. También pueden causar problemas de versiones; por ejemplo, si desea que su aplicación funcione tanto con Excel 2003 como con Excel 2007, deberá implementar ambos PIA con su aplicación.
La característica de tipo de interoperabilidad incorporada se integra directamente en la aplicación, pero solo los tipos y miembros de PIA que son absolutamente necesarios, por lo que no es necesario implementar PIA en la computadora del usuario final.
Para habilitar esta característica para un objeto existente (está habilitada de forma predeterminada para nuevas referencias), seleccione la referencia en el Explorador de soluciones y cambie la opción Incrustar tipos de interoperabilidad en la ventana Propiedades (consulte la Figura 5). Alternativamente, si compila con el compilador de línea de comando ming, use el modificador /l (o /link) en lugar de /r y /reference.
Figura 5 Habilitación de tipos de interoperabilidad integrados en el Explorador de soluciones
Después de habilitar esta función, la aplicación ya no dependerá de PIA. De hecho, si abre el ensamblaje en Reflector o ildasm, notará que en realidad no hay ninguna referencia al PIA.
Múltiples objetivos
La mejor parte de todas las funciones de Visual Basic 2010 es que puede usarlas incluso en proyectos destinados a .NET Framework 2.0 hasta .NET Framework 3.5. Esto significa que características como caracteres de continuación de línea implícitos, literales de matriz, inicializadores de colección, lambdas de declaración, propiedades implementadas automáticamente, etc. estarán disponibles en proyectos existentes sin tener que reorientar .NET Framework 4.
La excepción son los tipos de interoperabilidad integrados, que se basan en tipos que solo están disponibles en .NET Framework 4, por lo tanto, si apunta a las versiones 2.0 a 3.5 de .NET Framework, no puede usar esta característica; Además, los tipos marcados como variables solo se marcan como estaban en .NET Framework 4, por lo que en el ejemplo anterior, si apunta a las versiones 2.0 a 3.5, aún debe llamar a .Cast(Of T). Sin embargo, si apunta a estas versiones anteriores, puede crear sus propios tipos de variables (usando los modificadores de entrada/salida).
Para cambiar el marco de destino actual de su aplicación, haga doble clic en Mis proyectos, haga clic en la pestaña Compilar, haga clic en Opciones avanzadas de compilación y luego seleccione en el cuadro combinado en la parte inferior.
En realidad, no existe un interruptor de línea de comando de Ming para habilitar esta función al compilar desde la línea de comando de Ming. En efecto, el compilador observa qué ensamblado proporciona la definición de System.Object (generalmente mscorlib) y a qué marco está dirigido el ensamblado, y luego marca ese valor en el ensamblado de salida. (El compilador usa este mismo mecanismo cuando genera ensamblados Silverlight). Cuando se usa un IDE, todo esto sucede de forma transparente, por lo que normalmente no tienes nada de qué preocuparte.
Bienvenido a probar
Como puede ver, Visual Basic 2010 tiene muchas características poderosas que le permiten ser más productivo mientras escribe menos líneas de código y deja que el compilador haga más trabajo. En este artículo, solo analicé las características del lenguaje, pero hay innumerables mejoras excelentes en el IDE de Visual Basic 2010. Algunas mejoras se enumeran a continuación:
Navegar a
Destacar citas
generado por el uso
Mejor IntelliSense (coincidencia de subcadenas, búsqueda de camelcase, patrones de sugerencias: útil para probar primero su estilo de desarrollo)
Soporte para múltiples monitores
Zoom
El equipo de Visual Basic está ansioso por escuchar sus comentarios sobre nuestros esfuerzos para mejorar Visual Basic, así que envíenos sus comentarios y preguntas sobre Microsoft Connect. Para obtener más información sobre el lenguaje y las características del IDE, consulte el contenido en msdn.com/vbasic, que incluye artículos, ejemplos y videos instructivos. Por supuesto, la mejor manera de aprender es profundizar y utilizar el producto, por lo que es hora de instalarlo y probarlo.