Concepto · tipos
var frente a tipos explícitos en C#
El malentendido más común: var no es tipado dinámico. La variable sigue teniendo exactamente un tipo, elegido por el compilador a partir del lado derecho — simplemente no lo escribiste tú.
Qué hace realmente var
El tipo sale del lado derecho, en tiempo de compilación. En Visual Studio este programa imprime los tipos — y nunca cambian después:
var precio = 9.99; // double — porque 9.99 es un literal double
var cantidad = 42; // int — porque 42 es un literal int
var nombre = "Ada"; // string
Console.WriteLine(precio.GetType()); // System.Double
Console.WriteLine(cantidad.GetType()); // System.Int32
Console.WriteLine(nombre.GetType()); // System.String
(La reflexión .GetType() no está en el subconjunto del motor — las afirmaciones de abajo se verifican con comprobaciones que sí se ejecutan aquí.)
El chequeo estricto de tipos del motor demuestra lo mismo en vivo — una variable var se comporta exactamente como su tipo inferido:
var x = 9.99; // x es double desde esta línea
int y = x; // CS0266: exactamente como si hubieras escrito 'double x = 9.99;'
Si var fuera dinámico (como en JavaScript), esa asignación habría compilado. No lo hizo — porque x es un double en todos los sentidos, solo que inferido.
Dos trampas de literales que conviene conocer antes del día uno
var a = 7 / 2.0; // double: 3.5
var b = 7 / 2; // int: 3 — ¡división entera, fracción perdida!
Console.WriteLine(a);
Console.WriteLine(b);
var copia fielmente lo que produjo la expresión — incluidas las sorpresas de la división entera (historia completa: por qué 7 / 2 es 3).
Cuándo brilla var
Usa var cuando el tipo ya es obvio en la misma línea — entonces es pura reducción de ruido:
var nombres = new List<string>(); // obviamente List<string>
var perro = new Perro("Rex", 3); // obviamente Perro
var total = precio * cantidad; // bien cuando los tipos son simples
El caso de contenedores genéricos es donde más se siente — compara:
Dictionary<string, List<int>> notas = new Dictionary<string, List<int>>(); // escrito dos veces
var notas2 = new Dictionary<string, List<int>>(); // escrito una vez
var notas = new Dictionary>();
notas["Ada"] = new List { 90, 85 };
Console.WriteLine($"Ada tiene {notas["Ada"].Count} notas");
Cuándo gana el tipo explícito
Escribe el tipo cuando es información que el lector no puede ver de otra forma:
- Intención numérica:
double promedio = total / count;documenta que esperas fracción.var promedio = total / count;heredainten silencio si ambos son int — un bug disfrazado. - Resultados de API:
var usuario = ObtenerUsuario(id);obliga al lector a hacer hover o saltar.Usuario usuario = ObtenerUsuario(id);se lee solo. - Tipos parecidos:
decimalvsdoublepara dinero — la diferencia importa yvarla esconde.
var etiqueta = "cuenta: ";
int n = 5;
Console.WriteLine(etiqueta + n); // bien: string + int concatena
var mal = n = etiqueta; // tontería a propósito: string dentro de un int
Reglas que var debe cumplir
- Debe tener inicializador —
var x;es ilegal (¿qué tipo sería x?). - No puede cambiar de tipo después — una vez inferido, queda fijo como cualquier declaración.
- No es el
varde JavaScript, nidynamic— eldynamicde C# es otra palabra clave (rara) que salta el chequeo en compilación.
Convenciones de equipo, comprimidas
| Situación | Usa | Por qué |
|---|---|---|
new en la misma línea | var | El tipo ya está escrito a la derecha |
| Declaraciones numéricas | explícito | int vs double es información que sostiene la lógica |
| Resultados de métodos | explícito (o un buen nombre) | El lector no debería tener que buscarlo |
| LINQ / genéricos complejos | var | El nombre completo del tipo sería más largo que la lógica |
Casi todas las guías de estilo (incluida la de Microsoft) aterrizan en: usa var cuando el lado derecho hace obvio el tipo; si no, escríbelo. Cuando dos veteranos discuten, casi siempre discuten sobre qué cuenta como "obvio".