初学 C# 时,我写了不少控制台小程序。回头看,真正让我进步的并不是代码量,而是对其中几个典型片段的反复琢磨。这篇文章就挑出那些最有代表性的代码,说清楚要点和可以延伸的地方。

1. 输入解析:为什么推荐 TryParse

原代码

Console.Write("请输入第一个整数");
string str1 = Console.ReadLine();
int add1 = int.Parse(str1);

要点
这段代码在用户正常输入时完全没问题,但一旦用户输入了字母或空内容,程序就会崩溃。int.Parse 的职责只是转换,遇到非法输入直接抛异常。

延伸
在实际项目中,用户输入是不可控的。更稳健的做法是使用 int.TryParse

if (int.TryParse(Console.ReadLine(), out int add1))
    Console.WriteLine($"成功转换:{add1}");
else
    Console.WriteLine("请输入一个有效的整数");

总结:凡是处理外部输入的地方,都优先考虑 TryParse 模式,而不是让异常成为流程的一部分。

2. 三元运算符:简洁与清晰的边界

原代码

string Parity = num1 % 2 == 0 ? "偶数" : "奇数";
string singed = num1 > 0 ? "正数" : (num1 == 0 ? "0" : "负数");

要点
第一行非常清晰,是三元运算符的经典用法。第二行就有些绕了——嵌套三元表达式需要读者自己数括号,可读性下降。而且我最初还犯过一个错:把 == 写成了 =,好在 C# 编译器会直接报错,这恰恰体现了 C# 强类型带来的保护。

延伸
如果条件逻辑开始嵌套,不如换成 if-else

string signed;
if (num > 0) signed = "正数";
else if (num == 0) signed = "0";
else signed = "负数";

没必要为了“写得短”而牺牲可读性。三元运算符适合简单、非此即彼的判断,一旦上强度,就该收手。

3. 循环跳过:continue 的真实作用

原代码

for (int i = 1; i <= 50; i++)
{
    if (i % 10 == 7 || i % 7 == 0)
        continue;
    Console.Write($"{i},");
}

要点
这里用 continue 跳过了“含7”或“7的倍数”的数字。continue 并不是终止循环,而是结束本次迭代,立刻进入下一次循环判断。这和小游戏的需求完美契合。

延伸
很多初学者容易混淆 breakcontinue

  • break 是直接跳出整个循环体;
  • continue 是跳过本轮循环中剩余的代码,进入下一轮。

在这个例子里,如果把 continue 误写成 break,那遇到第一个满足条件的数字后,整个输出就结束了,这显然不是我们要的效果。

4. 冒泡排序:理解算法,更要理解边界

原代码

int temp = 0;
for (int i = 1; i <= score.Length - 1; i++)
{
    for (int j = 0; j < score.Length - i; j++)
    {
        if (score[j] > score[j + 1])
        {
            temp = score[j];
            score[j] = score[j + 1];
            score[j + 1] = temp;
        }
    }
}

要点
外循环控制“多少轮”,内循环负责“两两比较并交换”。内循环的结束条件 score.Length - i 是核心——每一轮结束后,最大的元素已经沉底,下一轮就可以少比一个。

延伸
写排序算法时最容易出错的就是循环边界。不妨在心里画一个数组,用一个小例子手动跑一遍,确认 j < score.Length - i 会不会越界。另外,C# 里其实有更便捷的写法:(score[j], score[j+1]) = (score[j+1], score[j]);,利用元组交换,不用临时变量,更简洁。

5. 数组去重:利用 IndexOf 的巧妙思路

原代码

int[] num10 = { 10, 33, 51, 41, 33, 62, 86, 35, 88, 42 };
int[] newnum10 = new int[num10.Length];
int count = 0;

for (int i = 0; i < num10.Length; i++)
{
    if (Array.IndexOf(newnum10, num10[i]) == -1)
        newnum10[count++] = num10[i];
}

要点
这段代码先创建一个空数组,然后遍历原数组,用 Array.IndexOf 检查当前元素是否已在新数组里。如果不存在(返回 -1),就添加进去。最后 count 就是去重后的元素个数。

延伸
这个方法的优点是思路清晰,适合初学者理解“去重”的逻辑。缺点也很明显:IndexOf 每次都会遍历新数组,时间复杂度是 O(n²),数据量大时效率低。更高效的做法是用 HashSet<int>,它利用哈希表自动去重,代码也极短:

HashSet<int> set = new HashSet<int>(num10);
int[] result = set.ToArray();

不过,在学习阶段,手写去重逻辑能加深对数组和循环的控制能力,之后再使用现成工具,就能做到知其然也知其所以然。

整体总结

从这几个例子可以提炼出几条通用的编程经验:

  1. 处理外部输入时要防御:能 TryParse 就不要 Parse
  2. 语法糖要适度:三元运算符不嵌套,交换用元组,可读性优先。
  3. 循环和条件判断是基本功:弄清楚 breakcontinue 的区别,手动演绎边界值。
  4. 先理解思路,再优化工具:自己实现排序和去重,是为了打好基础,之后再放心地使用内置方法。

这些控制台小程序看似简单,但把每个点想透、写稳,就是编程能力实实在在的提升。希望这篇回顾能帮你更有方向地回头审视自己写过的代码。

更多推荐