DNM+ Online
dotnetmania 2.0
Visual Basic ¿lenguaje dinámico?
En la próxima versión de .NET Framework (la 4.0) se incluirá lo que se conoce como DLR (Dynamic Language Runtime), que viene a ser el motor de ejecución de los lenguajes dinámicos de .NET. De esa forma, se permitirá al CLR (y por extensión a los lenguajes como VB y C#) el acceso de forma dinámica a los miembros de los objetos que haya en memoria, algo parecido a lo que siempre se ha conocido como late binding... o casi...

Dinámico, estático, ¿cuál es la diferencia?

En el contexto de este artículo, dinámico y estático se puede aplicar de dos formas, uno haciendo referencia a los tipos de datos y otro a los lenguajes. Cuando se habla de dinámico y estático haciendo referencia a los tipos de datos, estático significa que los tipos de datos solo soportan los elementos que ellos definen; es decir, solamente podemos acceder a los métodos, propiedades, etc., que estén definidos en el tipo. Por otro lado, dinámico significa que sin necesidad de conocer de antemano el tipo de datos que estamos usando, podamos acceder a cualquiera de los miembros (métodos, propiedades, etc.) que ese tipo defina (no confundamos esto con el polimorfismo, que si bien se puede parecer no es exactamente lo mismo). Aunque otra interpretación puede ser que esos tipos dinámicos no son específicos, sino que un mismo tipo (que en realidad ni es un tipo) soporta cualquier valor, algo parecido al tipo Variant de COM (o de VB6). Y por último, si ese tipo dinámico es producido por un lenguaje orientado a objetos, posiblemente sea una referencia a un objeto de un tipo que se ha inferido según el valor asignado, algo parecido a lo que hacen VB.NET y C# con la inferencia de tipos; la diferencia estará que los lenguajes estáticos habrán definido esas variables con un tipo de datos, mientras que los lenguajes dinámicos no suelen tener la necesidad (ni la obligación) de definir las variables. Cuando dinámico y estático se aplican a los lenguajes (para simplificar), estático significa que el lenguaje utiliza tipos estáticos, es decir especificaciones concretas para cada tipo de datos, mientras que los lenguajes dinámicos no necesitan definir esos tipos de datos, ya que suelen inferirse y el intérprete (los lenguajes dinámicos suelen tratarse como los lenguajes de script, y éstos suelen ser interpretados en lugar de compilados) inferirá el tipo según el valor asignado. En el resto del artículo nos centraremos en los tipos de datos más que a los lenguajes.

Visual Basic y los tipos dinámicos A los lectores que conozcan o hayan usado alguna versión de Visual Basic (da igual si es para .NET o no), todo lo comentado seguramente les sonará de algo. Simplificando, podríamos decir que el acceso dinámico a los miembros de un objeto es lo que llaman en inglés late binding (enlace tardío) y el acceso estático lo que se conoce como early binding (enlace temprano), algo que en Visual Basic siempre ha existido. El enlace estático (o temprano) solo permite acceder a los miembros "conocidos" del tipo, es decir, los miembros que esa clase (o tipo) defina; esto está bien y es lo que siempre nos han recomendado (cuando los que ahora lo recomendamos estábamos aprendiendo), entre otras cosas porque la ejecución es más rápida y sobre todo menos propensa a errores. Incluso hay lenguajes como C# que solo permiten esta forma de enlace, al menos hasta ahora, ya que su próxima versión (la 4.0) sí que soportará el enlace dinámico además del estático. Por otra parte, el enlace dinámico (o tardío) nos permite hacer referencia a miembros que no existen en el tipo de datos que estamos usando. Para que esto sea posible, el tipo debe ser de uso general (en .NET de tipo Object, ya que todos los tipos de .NET se derivan de ese tipo básico). Es decir, el compilador aceptará el acceso a ese miembro que no está definido en el tipo de datos y será en tiempo de ejecución cuando se compruebe si ese miembro está realmente definido; por eso lo de "enlace tardío", ya que hasta que no se ejecute ese código no se podrá comprobar el tipo de datos que realmente tiene ese "objeto". Aclarar que actualmente este tipo de enlace tardío en los lenguajes de .NET solo se permite en Visual Basic, pero no en C#, aunque esto cambiará en la próxima versión. En el listado 1 podemos ver cómo acceder a un método inexistente en la clase Object, pero que en realidad el objeto referenciado por la variable obj1 sí que define, y por tanto este código funcionará perfectamente. La salvedad es que si estamos usando Visual Basic 2008, además de usar Option Strict Off, también deberíamos desactivar la inferencia automática de tipos, con idea de que por defecto las cosas se hagan como se deben hacer (definiendo expresamente la variable del tipo de datos que va a contener); por tanto, lo mejor es definir expresamente la variable obj1 como de tipo Object. El método Mostrar usado desde la variable obj1 está definido en la clase MiClase, por tanto la llamada a ese método funcionará cuando se ejecute la aplicación. Si el lector piensa que lo correcto hubiera sido declarar la variable obj1 del tipo MiClase, decirle que estaría en lo cierto, pero aquí he usado esa clase para que la variable tuviera algo, ya que lo habitual es que ese valor se obtuviera de alguna forma en la que no tengamos forma de comprobar que en realidad tiene ese valor, como podría ser si esa variable se asignara mediante una llamada a CreateObject, tal como vemos en el listado 2. La desventaja de usar el enlace tardío radica en el hecho de que el compilador no hace ninguna comprobación de que ese miembro realmente esté definido en el tipo de datos, y por tanto es posible que el código falle en tiempo de ejecución, y ya sabemos que no hay nada peor que nuestra aplicación falle cuando esté ejecutándose en el equipo de nuestros clientes. Por otro lado, hay situaciones en las que puede ser útil usar ese enlace dinámico, normalmente cuando usamos otros objetos que no proceden del propio .NET Framework, por ejemplo si usamos objetos COM procedentes de aplicaciones como Office, tal como acabamos de ver en el listado 2.

Visual Basic puede ser no estricto, pero no es dinámico Tal como están las cosas actualmente, y de forma predeterminada (algunos seguimos lamentando que esto sea así), Visual Basic no es estricto a la hora de hacer conversiones o de acceder a los miembros de un objeto; es decir, se puede utilizar el enlace tardío a la hora de acceder a los miembros que no estén definidos expresamente (estáticamente) en un tipo en particular. Pero esto no significa que Visual Basic sea dinámico en el aspecto de permitir acceder dinámicamente a los miembros de un objeto, sino que lo simula y a la larga se obtienen los mismos resultados. La única forma de permitir que Visual Basic simule ser un lenguaje dinámico (en lo referente a acceder dinámicamente a los miembros de un objeto) es desactivando Option Strict. El problema es que esto es algo que muchos no recomendamos que se haga, y esperemos que no se justifique el hacerlo por la necesidad de acceder dinámicamente a los miembros de un tipo del que no tenemos la información de los miembros que expone públicamente. Ámbitos de Option Strict Afortunadamente, Visual Basic nos permite usar Option Strict (ya sea activado o desactivado) a dos niveles, y el nivel más bajo (o reducido) en el que se puede utilizar es a nivel de fichero de código; es decir, podemos restringir la comprobación no estricta solo en el código que esté definido dentro de un fichero de código. Esto, unido a que podemos definir clases parciales, nos permite definir en esos ficheros de código solo aquellas partes de nuestros tipos que necesiten que la comprobación estricta del código no esté activada, ya que es esa comprobación estricta que se hace al tener activado Option Strict la que no nos permite acceder a miembros de un objeto que no estén definidos en el tipo de ese objeto, o sea cuando usamos lo que ahora se llama acceso dinámico. El otro ámbito de Option Strict es a nivel de proyecto, ya que podemos indicar que, por ejemplo, cierto estado esté activado en todo el proyecto. De esta forma, si no indicamos expresamente el estado de esta opción de comprobación estricta, siempre estará activado o desactivado, dependiendo del valor que hayamos dado en las opciones del proyecto. Tal y como hemos visto en el párrafo anterior, cuando necesitemos desactivar esa comprobación estricta lo podremos hacer a nivel de fichero de código; de esa forma, solamente en ese fichero se dejará de hacer las comprobaciones que el compilador hace cuando asignamos el valor On a Option Strict. Recapitulando sobre Option Strict A título de recordatorio (así valdrá para aquellos lectores que no suelen utilizar Visual Basic y por tanto puede que no sepan para qué sirve esta instrucción) activando Option Strict el compilador nos obligará a definir todas las variables con un tipo de datos adecuado; además, a la hora de asignar un valor a esas variables se comprobará que el tipo de datos asignado es el mismo que el de la variable que recibe el valor o se puede convertir de forma implícita (automáticamente). Y cuando estamos asignando valores entre variables de distintos tipos de datos, también se comprobará si se puede hacer de forma implícita o se necesita hacer una conversión explícita (cast); en este último caso, la presencia en el código de esa conversión explícita nos pondrá en alerta de que es posible que dicha conversión falle y por tanto tengamos cuidado con ese código, ya que según la Ley de Murphy, si algo puede fallar, seguro que fallará. Cuando instalamos Visual Studio (o Visual Basic Express) el valor predeterminado de Option Strict es Off, es decir, desactivado; por tanto, todas estas comprobaciones que he comentado antes no se hacen. De esa forma, podemos declarar variables sin necesidad de indicar de qué tipo son y asignarles valores de cualquier tipo. Esto es posible ya que esas variables en realidad son de tipo Object y este tipo de datos acepta cualquier valor; por tanto, podremos asignar cualquier valor a una variable que sea de tipo Object. ¿Qué problema hay al usar Option Strict Off? Problema, lo que se dice problema, no hay ninguno. De hecho, mucha gente piensa que incluso es mejor tener desconectada esa opción, ya que así no tenemos que preocuparnos en hacer conversiones entre tipos ni tener que declarar las variables con un tipo de datos determinado. Pero no nos engañemos: está demostrado que una programación con tipos de datos concretos es más eficiente que una que utilice tipos de datos más generalizados (por no decir "genéricos", que se podría confundir con los tipos generic), y todo el trabajo que nos dará tener que hacer las conversiones de forma explícita nos ayudará a saber qué es lo que estamos haciendo y (como dije antes) alertarnos de que algo puede ir mal al hacer la conversión. Y es que el compilador de Visual Basic a la hora de hacer las conversiones entre tipos diferentes de datos lo hará casi de la misma forma que lo haremos nosotros, pero será más difícil de saber que se puede producir un fallo al convertir entre esos dos valores si no vemos que ahí se está haciendo una conversión.

Los tipos dinámicos en .NET Framework 4.0 Aunque aún está en una fase muy temprana de desarrollo (a la hora de escribir este artículo solo está disponible la primera CTP), .NET Framework 4.0 incluirá soporte para los tipos dinámicos, ya que también permite mediante el DLR la integración con lenguajes dinámicos y por tanto, se podrá intercambiar información entre esos lenguajes y los denominados estáticos. Para permitir la utilización de los tipos dinámicos en lenguajes como C# (que son muy estrictos), se ha tenido que hacer uso de una nueva forma de definir esos tipos dinámicos, ya que el compilador no debe comprobar si los miembros que se aplican a ese objeto están definidos o no; al menos, esa comprobación no se hará en tiempo de compilación, si no que será en tiempo de ejecución cuando se compruebe si realmente el objeto asignado a esa variable dinámica soporta ese método o propiedad que se está usando. En C# 4.0 se definirá un tipo dinámico con la palabra clave dynamic; en cuanto el compilador se encuentre con esa declaración, sabrá que debe aplicar late binding a esa variable, y por tanto no hacer ningún tipo de comprobación hasta que se esté ejecutando el código. En el listado 3 vemos un ejemplo parecido al del listado 1, solo que en esta ocasión estamos usando código de C# 4.0 y particularmente de la instrucción dynamic y lo que el uso de esa instrucción supone: enlace tardío. En Visual Basic no se ha añadido ninguna nueva instrucción para definir este tipo de variables dinámicas, ya que Visual Basic permite usar ese modo "retardado" de comprobación si se utiliza Option Strict Off. Pero no nos confundamos: eso no es un tratamiento dinámico de los tipos de datos, ya que en realidad, para permitir que todo esto sea posible, se ha agregado una nueva interfaz para definir estos tipos dinámicos; esa interfaz es IDynamicObject, que está definida en el espacio de nombres System.Scripting.Actions, y Visual Basic no utiliza esta interfaz, sino que simplemente hace lo que ha estado haciendo durante muchos años: esperar a que llegue el momento de la ejecución del código, y en ese preciso momento es cuando comprueba si el objeto define o no ese método (o cualquier otro miembro al que queramos acceder). Si lo define, bien; si no lo define, mal y de regalo una excepción. ¿Será Visual Basic un lenguaje dinámico? Tal como están las cosas, la respuesta es no. Al menos en lo que se refiere a los tipos dinámicos, ya que la intención es que llegue a serlo, es decir, que vuelva a ser un lenguaje de script o casi, ya que ahora a ese tipo de lenguajes se les llama dinámicos. Pero todo esto lo comprobaremos más adelante, cuando la próxima versión de Visual Basic (y de .NET Framework) esté más madura. Mientras tanto, contentémonos con lo que tenemos y aprovechémoslo; en esta isla seguiré explicando cosas para aprovechar mejor este lenguaje. Conclusiones En este artículo hemos hablado sobre algo que en los próximos meses (o años) seguramente será algo más habitual: los tipos y lenguajes dinámicos. Pero como hay que estar en la realidad, también hemos visto (aprovechando la coyuntura del tema) cómo Visual Basic puede ser dinámico o lo que es lo mismo, menos estricto con los tipos de datos que utilizamos en nuestras aplicaciones. Confío en que el lector sepa con más certeza que esa forma de dinamismo no es la más recomendable, salvo que realmente sepamos qué es lo que estamos haciendo, y en que después de esta lectura el lector sabrá qué es lo que hace en cada momento, o al menos sabrá cómo ser estricto a la hora de escribir el código o no serlo, si así lo considera oportuno.

blog comments powered by Disqus
autor
referencias