C# 控制台程序里,用户敲进来的所有内容最初都是字符串。哪怕用户输入的是 123,程序拿到的也是一个文本类型的值,不能直接参与加减乘除。想要把它变成真正的整数,就必须经过一次类型转换。这个看似简单的动作,恰恰是新手程序频繁崩溃的重灾区:用户随手输入一个字母或者直接按回车,程序立刻抛出异常退出。本文把几种主流的转换方式掰开揉碎讲清楚,让你明白什么场景该用哪一个。

一、为什么输入需要转换:理解 Console.ReadLine 的返回类型
先看最基础的读取代码。Console.ReadLine() 的返回类型是 string,并且可能为 null(旧版本编译环境下)。它的职责只是把用户按下回车之前输入的一整行字符原样交给你,不做任何解析。这一点和 C 语言的 scanf 完全不同,C# 把解析工作完全交给了开发者。
string input = Console.ReadLine();
Console.WriteLine($"你输入的内容是:{input},类型是 {input.GetType().Name}");
// 输入 123,得到的依然是 string
正因为返回的是字符串,下面的代码想直接做数学运算就编译不过:
string input = Console.ReadLine(); // int result = input * 2; // 编译错误:string 不能乘以 int
所以核心问题变成:如何把 string 安全地变成 int。C# 提供了三条路:int.Parse、Convert.ToInt32 和 int.TryParse,三者行为差异明显,选错了会让程序埋下隐患。
二、三种转换方式对比:Parse、Convert 与 TryParse
1. int.Parse:最直接也最危险
int.Parse 语义清晰,就是把字符串解析为整数。但它对非法输入毫无容忍:遇到 null 抛 ArgumentNullException,遇到非数字或超范围抛 FormatException 或 OverflowException。如果你能百分百保证输入合法,用它最简洁;否则就是定时炸弹。
string input = Console.ReadLine(); int number = int.Parse(input); // 输入 "abc" 直接崩溃 Console.WriteLine(number * 2);
2. Convert.ToInt32:内部处理 null
Convert.ToInt32 与 int.Parse 大体等价,关键区别是对 null 的处理:int.Parse(null) 抛参数为空的异常,而 Convert.ToInt32(null) 返回 0。另外它还能接受 object、double 等其他类型做转换,四舍五入规则也与强制转换的截断行为不同(例如 2.5 会被舍入为 2,3.5 舍入为 4,即银行家舍入法)。对于字符串而言,非法输入同样会抛异常,健壮性并没有本质提升。
string input = Console.ReadLine(); int number = Convert.ToInt32(input); // null 返回 0,"abc" 仍抛异常
3. int.TryParse:推荐的安全写法
int.TryParse 不抛异常,而是返回一个 bool 表示是否成功,转换结果通过 out 参数带出。失败时结果为 0,程序可以继续运行并提示用户重新输入。这种「先尝试、后判断」的模式在处理用户输入时几乎总是最佳选择,因为用户输入本质上就是不可信数据。
string input = Console.ReadLine();
if (int.TryParse(input, out int number))
{
Console.WriteLine($"转换成功:{number},两倍是 {number * 2}");
}
else
{
Console.WriteLine("输入的不是有效整数,请重新运行程序。");
}
三者的行为差异可以汇总成下表:
| 方式 | 输入为 null | 输入含非数字 | 是否抛异常 |
|---|---|---|---|
| int.Parse | 抛 ArgumentNullException | 抛 FormatException | 是 |
| Convert.ToInt32 | 返回 0 | 抛 FormatException | 是 |
| int.TryParse | 返回 false | 返回 false | 否 |
三、写一个健壮的整数读取函数:循环重试直到成功
实际项目中,直接提示「请重新运行程序」体验太差。更好的做法是把读取逻辑封装成方法,配合 while 循环不断请求输入,直到拿到合法整数为止。同时注意一个细节:不同国家的用户可能习惯不同的负号或数字分隔符,TryParse 默认使用当前区域设置,一般场景下不必特意指定。
static int ReadInt(string prompt)
{
while (true)
{
Console.Write(prompt);
string input = Console.ReadLine();
if (int.TryParse(input, out int value))
{
return value;
}
Console.WriteLine("输入无效,请输入一个整数,例如 42 或 -7。");
}
}
// 使用示例
int age = ReadInt("请输入你的年龄:");
Console.WriteLine($"明年你 {age + 1} 岁。");
如果需要限制范围,比如年龄必须在 1 到 150 之间,可以在 TryParse 成功后再追加一层范围校验:
static int ReadIntInRange(string prompt, int min, int max)
{
while (true)
{
int value = ReadInt(prompt);
if (value >= min && value <= max)
return value;
Console.WriteLine($"数值必须在 {min} 到 {max} 之间。");
}
}
这个模式的好处是把「读取、验证、重试」全部封装在一个函数里,主流程代码保持干净,也不用到处写 try-catch。
四、进阶场景:命令行参数与文件中的整数
除了交互式输入,整数还常常来自命令行参数或文件。命令行参数通过 args 数组获取,每个元素都是字符串,同样需要 TryParse。注意空参数的情况要先判断 args.Length,避免索引越界。
static void Main(string[] args)
{
if (args.Length > 0 && int.TryParse(args[0], out int count))
{
Console.WriteLine($"将处理 {count} 条数据。");
}
else
{
Console.WriteLine("用法:程序名 <数量>");
}
}
从文件读取时,可以用 File.ReadAllLines 拿到每一行字符串,再逐行解析。对于大文件,建议用 File.ReadLines 流式读取,避免一次性加载全部内容占用过多内存。解析失败时记录行号有助于快速定位脏数据。
int lineNo = 0;
foreach (string line in File.ReadLines("numbers.txt"))
{
lineNo++;
if (int.TryParse(line.Trim(), out int value))
{
Console.WriteLine($"第 {lineNo} 行:{value}");
}
else
{
Console.WriteLine($"第 {lineNo} 行不是整数,已跳过:{line}");
}
}
另外提醒一点,如果需要处理超出 int 范围(约 ±21 亿)的数字,把 int.TryParse 换成 long.TryParse 或 BigInteger.Parse 即可,用法完全一致。掌握了「先尝试、后判断」的思路之后,无论整数从哪里来,你都能写出既安全又易读的转换代码。
C#输入转整数Console.ReadLineint.Parse修改时间:2026-09-05 16:22:45