C# 8.0本质论
上QQ阅读APP看书,第一时间看更新

1.4 控制台输入和输出

本章已多次使用System.Console.WriteLine将文本输出到命令控制台。除了能输出数据,程序还需要能接收用户输入的数据。

1.4.1 从控制台获取输入

可用System.Console.ReadLine()方法获取控制台输入的文本。它暂停程序执行并等待用户输入。用户按回车键,程序继续。System.Console.ReadLine()方法的输出,也称为返回值,其内容即用户输入的文本字符串。代码清单1.14和输出1.4是一个例子。

代码清单1.14 使用System.Console.ReadLine()

输出1.4

在每条提示信息后,程序都用System.Console.ReadLine()方法获取用户输入并赋给变量。在第二个System.Console.ReadLine()赋值操作完成之后,firstName引用值Inigo,而lastName引用值Montoya。

高级主题:System.Console.Read()

除了System.Console.ReadLine()还有System.Console.Read()方法。但后者返回与读取的字符值对应的整数,没有更多字符可用就返回–1。为获取实际字符,需将整数转型为字符,如代码清单1.15所示。

代码清单1.15 使用System.Console.Read()

注意,除非用户按回车键,否则System.Console.Read()方法不会返回输入。按回车键之前不会对字符进行处理,即使用户已输入了多个字符。

C# 2.0新增了System.Console.ReadKey()方法。它和System.Console.Read()方法不同,返回的是用户的单次按键输入。可用它拦截用户按键操作,并执行相应行动,比如校验按键或是限制只能按数字键。

1.4.2 将输出写入控制台

代码清单1.14是用System.Console.Write()而不是System.Console.WriteLine()方法提示用户输入名和姓。System.Console.Write()方法不在输出文本后自动添加换行符,而是保持当前光标位置在同一行上。这样用户输入就会和提示内容处于同一行。代码清单1.14的输出清楚演示了System.Console.Write()的效果。

下一步是将通过System.Console.ReadLine()获取的值写回控制台。在代码清单1.16中,程序在控制台上输出用户的全名。但这段代码使用了System.Console.WriteLine()的一个变体,利用了从C# 6.0开始引入的字符串插值功能。注意在Console.WriteLine调用中为字符串字面值附加的$前缀。它表明使用了字符串插值。输出1.5是对应的输出。

代码清单1.16 使用字符串插值来格式化

输出1.5

代码清单1.16不是先用Write语句输出"Your full name is",再用Write语句输出firstName,用第三条Write语句输出空格,最后用WriteLine语句输出lastName。相反,是用C# 6.0的字符串插值功能一次性输出。字符串中的大括号被解释成表达式。编译器会求值这些表达式,转换成字符串并插入当前位置。不需要单独执行多个代码段并将结果整合成字符串,该技术允许一个步骤完成全部操作,从而增强了代码的可读性。

C# 6.0之前则采用不同的方式,称为复合格式化。它要求先提供格式字符串来定义输出格式,如代码清单1.17所示。

代码清单1.17 使用复合格式化

本例的格式字符串是Your full name is {0} {1}.。它为要在字符串中插入的数据标识了两个索引占位符。每个占位符的顺序对应格式字符串之后的实参。

注意索引值从零开始。每个要插入的实参,或者称为格式项,按照与索引值对应的顺序排列在格式字符串之后。在本例中,由于firstName是紧接在格式字符串之后的第一个实参,所以它对应索引值0。类似地,lastName对应索引值1。

注意,占位符在格式字符串中不一定按顺序出现。例如,代码清单1.18交换了两个索引占位符的位置并添加了一个逗号,从而改变了姓名的显示方式(参见输出1.6)。

代码清单1.18 交换索引占位符和对应的变量

输出1.6

占位符除了能在格式字符串中按任意顺序出现,同一占位符还能在一个格式字符串中多次使用。另外,也可省略占位符。但每个占位符都必须有对应的实参。

注意 由于C# 6.0风格的字符串插值几乎肯定比复合格式化更容易理解,本书默认使用前者。

1.4.3 注释

本节修改代码清单1.17来添加注释。注释不会改变程序的执行,只是使代码变得更容易理解。代码清单1.19中展示了新代码,输出1.7是对应的输出。

代码清单1.19 为代码添加注释

输出1.7

虽然插入了注释,但编译并执行后产生的输出和以前是一样的。

程序员用注释来描述和解释自己写的代码,尤其是在语法本身难以理解的时候,或者是在另辟蹊径实现一个算法的时候。只有检查代码的程序员才需要看注释,编译器会忽略注释,因而生成的程序集中看不到源代码中的注释的一丝踪影。

表1.2总结了4种不同的C#注释。代码清单1.19使用了其中两种。

第10章将更全面地讨论XML注释,以及如何利用它们来生成文档。届时会讨论各种XML标记。

编程史上确有一段时期,如代码没有详尽的注释,都不好意思说自己是专业程序员。然而时代变了。没有注释但可读性好的代码,比需要注释才能说清楚的代码更有价值。如开发者发现需要写注释才能说清楚代码块的功用,则应考虑重构,而不是洋洋洒洒写一堆注释。写注释来重复代码本来就讲得清的事情,只会使代码变得臃肿并降低可读性,还容易过时,因为将来代码可能更改了但注释却没有来得及更新。

表1.2 C#注释类型

设计规范

·不要使用注释,除非代码本身“一言难尽”。

·要尽量写清楚的代码而不是通过注释澄清复杂的算法。

初学者主题:XML

XML(Extensible Markup Language,可扩展标记语言)是一种简单而灵活的文本格式,常用于Web应用程序以及应用程序间的数据交换。XML之所以“可扩展”,是因为XML文档中包含的是对数据进行描述的信息,也就是所谓的元数据(metadata)。下面是示例XML文件:

文件以header元素开始,描述XML文件版本和字符编码方式。之后是一个主要的book元素。元素以尖括号中的单词开头,比如<body>。结束元素需要将同一单词放在尖括号中,并为单词添加正斜杠前缀,比如</body>。除了元素,XML还支持属性。title="Essential C#"就是XML属性的例子。注意XML文件包含了对数据(比如“Essential C#”“Data Types”等)进行描述的元数据(书名、章名等)。这可能形成相当臃肿的文件,但优点是可通过描述来帮助解释数据。