编译错误 · 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 在保护你。