编译错误 · error CS0165
使用了未赋值的局部变量"x"
你读取了一个变量,但在此之前没有任何东西被存进去。与大多数语言不同,C# 拒绝塞给你一个默不作声的零——它把你拦在编译期,因为"意外读到垃圾"正是那种运行时永远查不出来的 bug。
亲眼看它发生
int total;
Console.WriteLine(total + 1); // total 声明了,但从没被赋值
int total; 预定了名字和存储——但没有往里放值。读它就是无意义操作,C# 直说。最简单的修法:
int total = 0;
Console.WriteLine(total + 1);
有意思的情况:赋值了,但不是"明确赋值"
CS0165 真正想教的是:变量必须在每一条能到达读取点的路径上被赋值。在 if 里赋值不算数——编译器会替"条件不成立的那个分支"做打算:
string label;
if (score > 50)
{
label = "pass"; // 只在条件成立时赋值
}
Console.WriteLine(label); // error CS0165: 那 score 是 30 呢?
(完整的分支分析超出浏览器引擎的简化检查——引擎只验证"读取前是否赋过值";Visual Studio 应用的是这里展示的完整"每条路径"规则。)
修法一:分支前先给个合理的默认值
void Report(int score)
{
string label = "fail"; // 默认值覆盖所有路径
if (score > 50)
{
label = "pass";
}
Console.WriteLine(label);
}
Report(90);
Report(30);
修法二:让编译器证明赋值了——加上 else
int x = -5;
string sign;
if (x > 0)
{
sign = "positive";
}
else
{
sign = "negative or zero";
}
Console.WriteLine(sign); // OK: if+else 覆盖所有路径,编译器满意
修法三:声明时就初始化(惯用默认)
int sum = 0; // 累加器从 0 起步——永远如此
for (int i = 1; i <= 5; i++)
{
sum += i;
}
Console.WriteLine("Sum after loop: " + sum);
为什么 C# 不把所有东西默认成 0?
类的字段确实有默认值(0、null、false)——因为类一定会跑构造器。局部变量没有,因为 C# 的设计者拍板:你没写过值就去读,几乎必然是 mistake。这个错误是语言在帮你——和 CS0029 同一种哲学:拒绝瞎猜,逼你说清楚。
常见问答
怎么修 C# 里的 CS0165?
局部变量在赋值前被读取时触发。累加器/计数器在声明时初始化(int sum = 0;);分支里赋值的,先给默认值或补 else 保证每条路径都赋值——单个 if 分支里的赋值不够。
为什么 C# 不把局部变量默认成 0?
类字段有默认值;局部变量没有是刻意设计——未赋值就读几乎必然是 bug,编译错误比默不作声的零好得多。
排查清单
- 累加器/计数器 → 声明时初始化(
int sum = 0;)。 - 分支里算出来的值 → 要么先给默认值,要么加
else让所有路径都赋值。 - 声明了打算后面填?可以——只是在赋值前别读;把读挪到赋值下面。
out参数算"被被调方赋值"——int.TryParse(s, out int n)合法,虽然你从没给n赋值。