Variables locales implicítamente tipadas en C#

Hasta la versión 3.0 de C#, la declaración de una variable se debía realizar indicando su tipo de datos antes del identificador elegido para la misma. También era muy frecuente definir en ese mismo momento su valor inicial, siguiendo un patrón similar al siguiente:

  string s = «cadena»;
Sin embargo, la declaración anterior es redundante. Si la constante «cadena» es un string, ¿por qué hace falta indicar que la variable s también lo es? Las variables locales implícitamente tipadas permiten obviar en su declaración el tipo que tendrán, dejando al compilador la tarea de averiguar cuál será en función de las variables o constantes que se usen al inicializarlo. Por tanto, será posible escribir código como:
  var x = XmlDateTimeSerializationMode.Local;
Y será equivalente a:

XmlDateTimeSerializationMode x = XmlDateTimeSerializationMode.Local;
  Creo que no hace falta decir cuál de ellas es más cómoda a la hora de programar, ¿no? Simplemente hemos indicado con la palabra var que preferimos que sea el compilador el que haga el trabajo sucio. Otro contexto donde este tipo de variables pueden facilitarnos la vida de forma frecuente es en los bucles for, foreach y bloques using:
  // Un ejemplo de bucle…
var chars = «Saludicos».ToCharArray();
foreach (var ch in chars)
{
Console.Write(ch); // ch es char
}

// Y ahora un bloque using…
using (var ctx = new AppContext())
{
// usamos ctx, que es de tipo AppContext
}

  También es importante la existencia de esta nueva forma de declaración para posibilitar la creación de objetos de tipo anónimo, es decir, aquellos cuya especificación de clase se crea en el mismo momento de su definición. Por tanto, una declaración como la siguiente será válida:
  var x = new { Nombre = «Juan», Edad = 23 };
Para no desviarme del objetivo de este post, otro día hablaremos más detenidamente de las clases anónimas, aunque adelantaré que una vez compilado el código anterior el resultado será algo parecido al siguiente:

class __Anonymous1
{
private string nombre ;
private int edad ;
public string Nombre { get { return nombre ; } }
public int Edad { get { return edad ; } }
public __Anonymous1(string nombre, int edad)
{
this.nombre = nombre;
this.edad = edad;
}
}

__Anonymous1 x = new __Anonymous1(«Juan», 23);

  Existen ciertas reglas de obligado cumplimiento para usar variables locales implícitamente tipadas:

  • La declaración debe incluir un valor de inicialización. En otras palabras, no será posible usar en una línea var i;, puesto que el compilador no podría inferir el tipo en este momento.

  • El valor de inicialización debe ser una expresión evaluable como clase en tiempo de compilación. Expresamente prohibido el valor null, es decir, nada de var n = null;, puesto que el compilador no sabría de qué tipo se trata; eso sí, si fuera necesario, podría forzarse un casting var str = null as string;.

  • La declaración no puede incluir más de una variable. Una línea como var i = 1, s = «hola»; generará un error en compilación.

  • El inicializador no puede referirse a la propia variable declarada, obviamente.

  • Sólo pueden utilizarse como variables locales en bloques de código, en bucles for y foreach y como recurso de un bloque using.
Por último, me gustaría añadir un par de detalles que considero interesantes. Seguimos teniendo Intellisense...Primero, el hecho de utilizar la palabra «var» y no indicar de forma explícita el tipo puede hacernos pensar que estamos utilizando tipado dinámico en tiempo de ejecución, como lo hacemos con Javascript, sin embargo esto no es así. Como he comentado anteriormente, el compilador toma el tipo del lado derecho de la asignación de inicialización, por lo que si la variable no es inicializada se produce un error de compilación:
Implicitly-typed local variables must be initialized (Las variables locales implícitamente tipadas deben ser inicializadas)

Por ello, un entorno como Visual Studio sabe en todo momento el tipo exacto de que se trata, y nos puede ofrecer las ayudas en la codificación, detección de errores sintáticos e intellisense, como se puede observar en la imagen.


Segundo, y muy interesante. Como ya comenté en su momento, la nueva versión de Visual Studio permite la generación de ensamblados para versiones anteriores de la plataforma, es decir, que es posible escribir código C# 3.0 y generar un ensamblado para el framework 2.0. Esto, a efectos prácticos, implica que una vez demos el salto definitivo a VS2008 podremos usar las variables locales de tipo implícito, así como otras novedades del lenguaje, incluso en aplicaciones diseñadas para .NET 2.0.



Publicado en: Variable Not Found.

6 comentarios sobre “Variables locales implicítamente tipadas en C#”

  1. Muy bueno el artículo, pero no entiendo que nos aporta realmente la utilización del tipo var, al final el compilador hace el trabajo que nosotros no realizamos, pero no es mas lógico si conocemos el dato declarar su tipo. En fin, en mi ignorancia no le veo ningún uso ya que tienes que inicializar el valor al mismo tiempo que declaras la variable,
    es una pena que haya que inicializarlo, sino se podria utilizar como un valor que te devuelva un tipo T de generics.

  2. Hola, Juan. Gracias por tu comentario.

    En mi opinión, aporta al menos dos cosas.

    La primera, nos ahorra tiempo al codificar (observa el primer ejemplo, con XmlDateTimeSerializationMode). La segunda, sirve como base para otras características de C#, como los objetos anónimos (que serían imposibles de implementar sin ellos), que a su vez, junto con otras características, posibilitan Linq (por ejemplo).

    En fin, que no es que sea la panacea, pero tampoco viene mal, ¿no crees?

  3. Bueno, no se, me hace dudar, pienso que tambien puede lugar a errores que de otra forma son mas dificiles de cometer, por ejemplo imaginate que quieres una variable decimal y realizas var myvar = 0; internamente este se convierte en un int y no en un decimal, el problema es que no puedo establecer por ejemplo una propiedad de tipo var, y posteriormente asignarle un valor, sino que te obliga a declararlo en el mismo momento, entiendo que es un object que el compilador formatea en tiempo de compilación. Es una pena, de otra forma si podriamos utilizarlo como un objeto anonimo y evitar el box y unbox. Creo que es una carencia importante que tiene Visual Studio a la que todavia no han dado una solución sobre todo en el uso de clases genericas que devuelven tipos T.

  4. Sí, ese caso que comentas se podría dar. Sin embargo, de la misma forma que ahora declaras double d = 0.0, podrías hacer var d=0.0 y sería lo mismo.

    En cuanto a la obligatoriedad de la inicialización, tienes toda la razón, aunque entiendo que está hecho así para forzar desde el primer momento el tipo, al igual que cuando se lo declaras de forma explícita.

  5. BRAVO BUENISIMO POST !!!!!!!!!!!!!

    UNA CONSULTA COMO LO HAGO LO MISMO PERO CON VISUAL STUDIO 2005 Y CON C# ?

    ESTABA APLICANDO REFLECTION PERO ESOY EN UNA LADILLA :s NO PUEDO LLEGAR A ESE TIPO.

    SI ALGUIEN ME PODRIA DAR UNA MANO CON ESTE TEMA
    LO AGRADECERIA MUCHO.

  6. Fernando, si te he entendido bien, me temo que no será posible.

    Se trata de una característica de C# 3.0, por lo que no podrás usarla en VS2005. En cambio, lo que sí podrías es utilizar VS2008 (que incluye C# 3.0) y compilar a framework 2.0.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *