編譯錯誤 · error CS0029
無法將型別"X"隱式轉換為"Y"
你把一種型別的值,放進了期待另一種型別的位置——而 C# 無法(或不肯)替你悄悄轉換。按一下下面壞程式碼的執行按鈕:報出來的錯誤和真實編譯器是同一套規則。
親眼看它發生
int count = "5"; // 帶引號的是文本,不是數量
編譯器拒絕瞎猜。"5"(帶引號)是 string——兩個字元,一個 '5',跟"數量"沒有任何關係。C# 當然可以試著去解析它,但猜錯了就是執行時崩潰,所以它在編譯期就把你攔下來。
四種常見成因(和修法)
1. string → int:你其實想解析
string input = "5";
int count = int.Parse(input); // 明確的轉換,解析失敗會拋 FormatException
Console.WriteLine(count + 1);
int.Parse 負責轉換,而且轉不動時會說實話。如果失敗是正常情況(比如使用者輸入),改用 int.TryParse(input, out int count)——返回 false 而不是拋異常。
2. 數字 → string:你其實想拼接
int apples = 3;
string msg = "You have " + apples + " apples"; // + 會自動呼叫 ToString()
Console.WriteLine(msg);
3. bool 和它的文本形式
bool ok = "true"; 報的是同一個錯。要顯式解析:
bool ok = bool.Parse("true");
Console.WriteLine(ok);
4. 型別不相關的物件
把 Dog 賦給 Car 變數,是同一個錯誤的類形式——根本不存在轉換:
class Dog { public string Name; }
class Car { public string Model; }
Dog d = new Dog { Name = "Rex" };
Car c = d; // CS0029: 無法將型別"Dog"隱式轉換為"Car"
近親:CS0266(那個"差一個強制轉換"的兄弟)
如果兩種型別可以轉換、但只能顯式轉——最典型的就是 double → int,會丟小數——你看到的會是 CS0266,提示語是"存在顯式轉換(是否缺少強制轉換?)":
double price = 9.99;
int rounded = price; // CS0266: 會悄悄丟掉 .99
double price = 9.99;
int rounded = (int)price; // 顯式轉換:"我知道,截斷它"
Console.WriteLine(rounded);
經驗法則:CS0029 = 不存在隱式轉換(去解析、去拼接、或者重新想型別);CS0266 = 轉換存在但必須自己寫出來,接受那份損失。
常見問答
CS0029 在 C# 裡是什麼意思?
CS0029 表示你把一種型別的值賦給了不存在隱式轉換的另一種型別的位置——比如 int count = "5";。修法:字串用 int.Parse(s) 解析;反向用 .ToString() 或 $"…" 插值拼文本;double 轉 int 用顯式 (int) 強轉(那種情況報的是 CS0266)。
CS0029 和 CS0266 有什麼區別?
CS0029 表示隱式轉換根本不存在(string 轉 int)——必須主動解析或轉換。CS0266 表示轉換存在但會丟資料(double 轉 int),所以編譯器要求你寫出顯式強轉,例如 (int)price。
排查清單
- 把錯誤資訊倒著讀:先報的是值的真實型別,後報的是期待的型別。
- 有引號就是
string,沒引號的數字才是數值。檢查你寫的是哪種。 - 往裡轉(字串 → 數字):
int.Parse/TryParse。 - 往外轉(數字 → 字串):和字串一起的
+、.ToString(),或$"…"插值。 - 會丟資料的數字轉換必須寫顯式
(int)強轉——那是 CS0266 在保護你。