Error del compilador · error CS0165

Uso de la variable local no asignada 'x'

Lees una variable antes de que algo se haya guardado en ella. A diferencia de la mayoría de lenguajes, C# se niega a darte un cero silencioso — te detiene en compilación, porque "leer basura por accidente" es justo el bug que nunca encuentras en ejecución.

Míralo ocurrir

int total;
Console.WriteLine(total + 1);   // 'total' se declaró pero nunca recibió valor

int total; reserva el nombre y el espacio — no pone un valor ahí. Leerla carece de sentido, y C# te lo dice. La solución trivial:

int total = 0;
Console.WriteLine(total + 1);

El caso interesante: asignar no es "definitivamente asignar"

La lección real de CS0165 es que C# exige que la variable esté asignada en todos los caminos que pueden llegar a tu lectura. Asignar dentro de un if no cuenta — el compilador planifica para la rama que no entra:

string etiqueta;
if (puntuacion > 50)
{
    etiqueta = "aprobado";          // solo se asigna si la condición se cumple
}
Console.WriteLine(etiqueta);        // error CS0165: ¿y si puntuacion era 30?

(El análisis completo de ramas excede la comprobación simple del motor: este valida "¿se asignó alguna vez antes de la lectura?"; Visual Studio aplica la regla completa de "todos los caminos".)

Solución 1: un valor por defecto razonable antes de la rama

void Informe(int puntuacion)
{
    string etiqueta = "suspenso";   // el valor por defecto cubre todas las rutas
    if (puntuacion > 50)
    {
        etiqueta = "aprobado";
    }
    Console.WriteLine(etiqueta);
}

Informe(90);
Informe(30);

Solución 2: que el compilador pueda probarlo — añade else

int x = -5;
string signo;
if (x > 0)
{
    signo = "positivo";
}
else
{
    signo = "negativo o cero";
}
Console.WriteLine(signo);   // OK: if+else cubre todas las rutas

Solución 3: inicializar en la declaración (el valor por defecto idiomático)

int sum = 0;                 // los acumuladores empiezan en 0 — siempre
for (int i = 1; i <= 5; i++)
{
    sum += i;
}
Console.WriteLine("Suma tras el bucle: " + sum);

¿Por qué no poner 0 por defecto en todo?

Los campos de una clase sí tienen valor por defecto (0, null, false) — porque una clase siempre ejecuta su constructor. Las locales no, porque los diseñadores de C# decidieron: si nunca escribiste un valor, leerlo es casi seguro un error. El error es el lenguaje ayudándote — la misma filosofía que CS0029: niega a adivinar, obliga a decir qué quieres.

Preguntas frecuentes

¿Cómo corrijo CS0165?

Se lee una local antes de asignarla. Acumuladores y contadores: inicializa al declarar. Valores calculados en ramas: valor por defecto o else que cubra todos los caminos.

¿Por qué no hay cero por defecto?

Los campos sí lo tienen; las locales no es deliberado — leer sin asignar casi siempre es un bug, y un error de compilación es mejor que un cero silencioso.

Lista de comprobación