首页 / C# 入门教程 / 类型转换

C# 入门教程

类型转换

本教程共 100 篇 · 第 12 篇 · 更新于 2026-07-31 · 约 9 分钟阅读

C#C# 入门教程类型转换ParseTryParsechecked

12. 类型转换

本节目标:掌握不同类型间如何安全转换,尤其是字符串与数字互转,以及怎么避免溢出陷阱。

不同类型之间常需要”换格式”:键盘读进来的是 string,计算要 int;小数结果要存成整数。这章把转换的几种姿势讲全。

隐式转换:编译器放心替你转

当目标类型”装得下”源类型,且不会丢信息,C# 自动转,叫隐式转换(implicit conversion):

namespace CSharpDemo;

int a = 100;
long b = a;        // int → long,安全,自动转
double d = a;      // int → double,安全,自动转

intlongintdouble 都不会丢数据,编译器直接帮你做了,不用写额外代码。

Note

隐式转换方向总是”小范围 → 大范围、不会失真”。反过来(大→小)编译器不敢自作主张,必须你显式说明,见下节。

为什么编译器敢自动转

隐式转换的前提是”绝不丢信息”。int 是 32 位,long 是 64 位,小盒子装进大盒子,值原封不动;intdouble 虽然类型变了,但整数都能精确表示,也不失真。编译器只在”数学上保证安全”时才替你转。一旦可能丢精度或溢出,它就罢工,逼你写强制转换——把”是否安全”的责任交还给你。这是 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.Parsedecimal.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,还有 isas 运算符能安全判断与转换,我们在类型模式(第 18、87 章)会系统讲到,是处理引用类型转换的常用手段。

常见疑问解答

问:为什么 int.Parse("3.14") 会报错? 因为 int 只能装整数,"3.14" 含小数点,格式不对。Parse 很严格,类型不匹配就抛异常。要转小数请用 double.Parsedecimal.Parse

问:TryParse 的 out 参数为什么能”带出”结果? out 参数允许方法把结果通过参数回传给你。调用时写 out int result,方法内部给 result 赋值,调用结束后你就能用。它是 C# 从方法”返回多个值”的标准手法。

问:Convert 和 Parse 选哪个? 来源可信、格式确定 → Parse 最直接;来源不可信(如用户输入)→ TryParse 最稳;需要跨多种类型灵活转换或容忍 nullConvert。按场景挑,没有绝对优劣。

要点速记

  • 小转大自动(隐式),大转小需强转(可能丢)。
  • 怕溢出用 checked 块让错误当场暴露。
  • 字符串转数字:Parse 抛错、TryParse 安全。
  • Convert 通用,但对用户输入仍推荐 TryParse

动手练一练

  1. 让用户输入一行文字,用 int.TryParse 转成整数,成功打印”转换成功”,失败打印”格式不对”。
  2. 故意 int.Parse("abc"),观察抛出的异常类型,理解 Parse 对格式有多严格。
  3. checked { byte b = (byte)300; }try/catch 接住溢出异常,体会 checked 的作用。

显式转换的陷阱清单

强转 (类型) 是个”危险动作”,列几个常见坑:

  1. 精度丢失(int)3.993,小数被直接截断而非四舍五入。
  2. 溢出绕回(byte)30044,超出范围的值被”绕回”。
  3. 引用转换失败:把父类引用强转为不相关的子类,运行时会抛 InvalidCastException
  4. 拆箱类型不符:把 object 里的 int 强转为 long 会失败,类型必须完全匹配。
Tip

强转前先问:“目标装得下吗?类型对得上吗?” 不确定就用 TryParseis/as,别用强转赌运气。

数字与字符串的来回

转换是双向的:数字 → 字符串用 ToString(),字符串 → 数字用 Parse/TryParse。这一来一回在”读配置、存文件、调接口”时天天发生。记牢这条主链路,绝大多数转换场景都能覆盖。

int n = 42;
string s = n.ToString();              // 数字 → 字符串
if (int.TryParse(s, out int back))    // 字符串 → 数字
{
    Console.WriteLine(back);          // 42
}

这条”来回通道”是程序与外部世界交换数据的命脉:外部(键盘、文件、网络)给的都是文本,程序内部算的是数字,转换就在中间搭桥。

小结与下一步

小转大自动(隐式),大转小要强转(可能丢)。字符串转数字用 ParseTryParse,后者更安全。怕溢出就包 checked。选哪个工具,核心看”来源可不可信”:内部数据可宽松,用户输入必须严。转换这关过了,字符串处理就是你下一站的重点。

下一章专讲字符串字面量:普通、逐字、插值、原始字符串,四种写法各管什么。