編譯錯誤 · 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,編譯錯誤比默不作聲的零好得多。

排查清單