类型转换
本教程共 100 篇 · 第 12 篇 · 更新于 2026-07-31 · 约 9 分钟阅读
12. 类型转换
本节目标:掌握不同类型间如何安全转换,尤其是字符串与数字互转,以及怎么避免溢出陷阱。
不同类型之间常需要”换格式”:键盘读进来的是 string,计算要 int;小数结果要存成整数。这章把转换的几种姿势讲全。
隐式转换:编译器放心替你转
当目标类型”装得下”源类型,且不会丢信息,C# 自动转,叫隐式转换(implicit conversion):
namespace CSharpDemo;
int a = 100;
long b = a; // int → long,安全,自动转
double d = a; // int → double,安全,自动转
int 转 long、int 转 double 都不会丢数据,编译器直接帮你做了,不用写额外代码。
Note隐式转换方向总是”小范围 → 大范围、不会失真”。反过来(大→小)编译器不敢自作主张,必须你显式说明,见下节。
为什么编译器敢自动转
隐式转换的前提是”绝不丢信息”。int 是 32 位,long 是 64 位,小盒子装进大盒子,值原封不动;int 转 double 虽然类型变了,但整数都能精确表示,也不失真。编译器只在”数学上保证安全”时才替你转。一旦可能丢精度或溢出,它就罢工,逼你写强制转换——把”是否安全”的责任交还给你。这是 C# 既省事又安全的设计取舍。
显式转换:你拍板,可能丢信息
目标类型比源类型”窄”,转换可能丢数据,得用强制转换(cast),在值前加 (类型):
double pi = 3.99;
int n = (int)pi; // 显式转换,结果 n = 3(直接截断小数)
Console.WriteLine(n);
注意:(int) 是截断不是四舍五入,3.99 变成 3。若想四舍五入,用 Math.Round 等先处理再转。
int big = 300;
byte small = (byte)big; // 溢出!byte 最大 255
Console.WriteLine(small); // 结果变成 44,数据错了
300 超出 byte 范围,强转后值被”绕回”,得到错误结果还不报错——这正是危险所在。
Tip强转前,最好先判断范围:
if (big <= byte.MaxValue) small = (byte)big;。别盲目相信输入。
checked:让溢出当场报错
如果你希望”一旦溢出就抛异常,而不是悄悄给错值”,用 checked 块:
try
{
checked
{
int big = 300;
byte small = (byte)big; // 这里会抛 OverflowException
}
}
catch (OverflowException)
{
Console.WriteLine("转换溢出,已捕获");
}
checked 让运行时严格检查算术与转换溢出。对安全性要求高的场景(尤其财务),checked 能帮你早发现问题。
Warning默认情况下 C# 不做溢出检查,溢出会”静默绕回”给错值,既不报错也不抛异常。在金额、计数、索引这类不能错的场合,忘了
checked可能导致账目对不上、数组越界等严重后果。这类场景宁可多写几行,把checked用上。
Parse:字符串转数字
从控制台或文件读到的都是 string,要算数得转成数字,用 int.Parse:
string input = "42";
int value = int.Parse(input); // "42" → 42
Console.WriteLine(value + 1); // 43
double.Parse、decimal.Parse 同理。decimal.Parse("9.99") 得到 9.99m。
Note
Parse遇到格式不对会直接抛异常。比如int.Parse("abc")立刻崩溃。所以 Parse 只适合”你百分百确定格式正确”的场合。
TryParse:安全地尝试转换
更稳妥的是 TryParse:它不抛异常,而是返回一个 bool 表示成功与否,结果通过 out 参数带出:
Console.Write("输入数字:");
string input = Console.ReadLine()!;
if (int.TryParse(input, out int result))
{
Console.WriteLine($"转换成功:{result}");
}
else
{
Console.WriteLine("输入的不是合法整数");
}
out int result 是”输出参数”:方法把结果填进去。判断返回的 bool,就知道转没转成。真实项目读用户输入,几乎都用 TryParse。
Tip记住口诀:格式可控用
Parse,来源不可信用TryParse。用户敲的键盘输入永远”不可信”,首选TryParse。
Convert:跨类型的通用转换
Convert 类提供一组通用方法,能在多种类型间转,且对 null 更宽容:
string s = "123";
int n = Convert.ToInt32(s); // 等价于 int.Parse
double d = Convert.ToDouble("3.14");
Convert.ToInt32(null) 返回 0 而不报错,这点与 Parse 不同。日常小工具里图省事可用,但读用户输入仍推荐 TryParse 拿布尔判断。
三者怎么选
| 来源 | 推荐 |
|---|---|
| 格式确定、内部数据 | Parse 最直接 |
| 用户输入等不可信来源 | TryParse 最稳 |
需要容忍 null、跨多类型 | Convert 通用 |
没有绝对的优劣,看”来源可不可信”这一条就够。
拆箱转换(了解即可)
值类型赋给 object 再取回,叫装箱/拆箱,涉及类型转换与性能,第 48 章细讲。这里先知道:object 和具体类型之间转换属于显式转换的一种。
数字转字符串也别忘了
前面讲”字符串转数字”,反过来”数字转字符串”用 ToString():
int n = 42;
string s = n.ToString(); // "42"
decimal price = 9.99m;
string text = price.ToString(); // "9.99"
需要特定格式时,ToString 支持格式符(如 "C" 货币、"D5" 补零),这部分我们在第 14 章字符串操作里详谈。这里先记住:int/decimal 都能 .ToString() 变回字符串。
子类父类间的转换
当类型有继承关系时,也能转换:子类可隐式转父类(“是一只”关系),父类转子类要显式强转且可能失败。这叫”引用类型转换”,属于面向对象章节的内容。这里先留个印象:可转换性取决于类型间的”是不是”关系,而非单纯写法。
Note不确定转换是否成功时,除了
TryParse,还有is和as运算符能安全判断与转换,我们在类型模式(第 18、87 章)会系统讲到,是处理引用类型转换的常用手段。
常见疑问解答
问:为什么 int.Parse("3.14") 会报错?
因为 int 只能装整数,"3.14" 含小数点,格式不对。Parse 很严格,类型不匹配就抛异常。要转小数请用 double.Parse 或 decimal.Parse。
问:TryParse 的 out 参数为什么能”带出”结果?
out 参数允许方法把结果通过参数回传给你。调用时写 out int result,方法内部给 result 赋值,调用结束后你就能用。它是 C# 从方法”返回多个值”的标准手法。
问:Convert 和 Parse 选哪个?
来源可信、格式确定 → Parse 最直接;来源不可信(如用户输入)→ TryParse 最稳;需要跨多种类型灵活转换或容忍 null → Convert。按场景挑,没有绝对优劣。
要点速记
- 小转大自动(隐式),大转小需强转(可能丢)。
- 怕溢出用
checked块让错误当场暴露。 - 字符串转数字:
Parse抛错、TryParse安全。 Convert通用,但对用户输入仍推荐TryParse。
动手练一练
- 让用户输入一行文字,用
int.TryParse转成整数,成功打印”转换成功”,失败打印”格式不对”。 - 故意
int.Parse("abc"),观察抛出的异常类型,理解Parse对格式有多严格。 - 写
checked { byte b = (byte)300; }用try/catch接住溢出异常,体会checked的作用。
显式转换的陷阱清单
强转 (类型) 是个”危险动作”,列几个常见坑:
- 精度丢失:
(int)3.99得3,小数被直接截断而非四舍五入。 - 溢出绕回:
(byte)300得44,超出范围的值被”绕回”。 - 引用转换失败:把父类引用强转为不相关的子类,运行时会抛
InvalidCastException。 - 拆箱类型不符:把
object里的int强转为long会失败,类型必须完全匹配。
Tip强转前先问:“目标装得下吗?类型对得上吗?” 不确定就用
TryParse或is/as,别用强转赌运气。
数字与字符串的来回
转换是双向的:数字 → 字符串用 ToString(),字符串 → 数字用 Parse/TryParse。这一来一回在”读配置、存文件、调接口”时天天发生。记牢这条主链路,绝大多数转换场景都能覆盖。
int n = 42;
string s = n.ToString(); // 数字 → 字符串
if (int.TryParse(s, out int back)) // 字符串 → 数字
{
Console.WriteLine(back); // 42
}
这条”来回通道”是程序与外部世界交换数据的命脉:外部(键盘、文件、网络)给的都是文本,程序内部算的是数字,转换就在中间搭桥。
小结与下一步
小转大自动(隐式),大转小要强转(可能丢)。字符串转数字用 Parse 或 TryParse,后者更安全。怕溢出就包 checked。选哪个工具,核心看”来源可不可信”:内部数据可宽松,用户输入必须严。转换这关过了,字符串处理就是你下一站的重点。
下一章专讲字符串字面量:普通、逐字、插值、原始字符串,四种写法各管什么。