{"id":284,"date":"2023-10-18T23:03:33","date_gmt":"2023-10-18T15:03:33","guid":{"rendered":"https:\/\/miie.net\/?p=284"},"modified":"2023-10-18T23:03:33","modified_gmt":"2023-10-18T15:03:33","slug":"pro-c10-chapter-3-core-c-programming-constructs-part-1","status":"publish","type":"post","link":"https:\/\/diji.net\/?p=284","title":{"rendered":"Pro C#10 CHAPTER 3 Core C# Programming Constructs, Part 1"},"content":{"rendered":"<h2>PART II<\/h2>\n<p>Core C# Programming<\/p>\n<h2>CHAPTER 3 Core C# Programming Constructs, Part 1<\/h2>\n<p>\u6838\u5fc3 C# \u7f16\u7a0b\u6784\u9020\uff0c\u7b2c 1 \u90e8\u5206<\/p>\n<p>This chapter begins your formal investigation of the C# programming language by presenting a number of bite-sized, stand-alone topics you must be comfortable with as you explore the .NET Core Framework. The first order of business is to understand how to build your program\u2019s application object and to examine the composition of an executable program\u2019s entry point: the Main() method as well as a new C# 9.0 feature,top-level statements. Next, you will investigate the fundamental C# data types (and their equivalent types in the System namespace) including an examination of the System.String and System.Text.StringBuilder classes.<br \/>\n\u672c\u7ae0\u901a\u8fc7\u4ecb\u7ecd\u4e00\u4e9b\u5728\u63a2\u7d22 .NET Core Framework \u65f6\u5fc5\u987b\u719f\u6089\u7684\u5c0f\u578b\u72ec\u7acb\u4e3b\u9898\uff0c\u5f00\u59cb\u5bf9 C# \u7f16\u7a0b\u8bed\u8a00\u8fdb\u884c\u6b63\u5f0f\u7814\u7a76\u3002\u9996\u8981\u4efb\u52a1\u662f\u4e86\u89e3\u5982\u4f55\u6784\u5efa\u7a0b\u5e8f\u7684\u5e94\u7528\u7a0b\u5e8f\u5bf9\u8c61\u5e76\u68c0\u67e5\u53ef\u6267\u884c\u7a0b\u5e8f\u5165\u53e3\u70b9\u7684\u7ec4\u6210\uff1aMain\uff08\uff09 \u65b9\u6cd5\u4ee5\u53ca\u65b0\u7684 C# 9.0 \u529f\u80fd\uff0c\u9876\u7ea7\u8bed\u53e5\u3002\u63a5\u4e0b\u6765\uff0c\u60a8\u5c06\u7814\u7a76\u57fa\u672c\u7684 C# \u6570\u636e\u7c7b\u578b\uff08\u53ca\u5176\u5728 System \u547d\u540d\u7a7a\u95f4\u4e2d\u7684\u7b49\u6548\u7c7b\u578b\uff09\uff0c\u5305\u62ec\u68c0\u67e5 System.String \u548c System.Text.StringBuilder \u7c7b\u3002<\/p>\n<p>After you know the details of the fundamental .NET Core data types, you will then examine a number of data type conversion techniques, including narrowing operations, widening operations, and the use of the checked and unchecked keywords.<br \/>\n\u4e86\u89e3\u57fa\u672c .NET Core \u6570\u636e\u7c7b\u578b\u7684\u8be6\u7ec6\u4fe1\u606f\u540e\uff0c\u60a8\u5c06\u68c0\u67e5\u8bb8\u591a\u6570\u636e\u7c7b\u578b\u8f6c\u6362\u6280\u672f\uff0c\u5305\u62ec\u7f29\u5c0f\u64cd\u4f5c\u3001\u6269\u5927\u64cd\u4f5c\u4ee5\u53ca\u9009\u4e2d\u548c\u672a\u9009\u4e2d\u5173\u952e\u5b57\u7684\u4f7f\u7528\u3002<\/p>\n<p>This chapter will also examine the role of the C# var keyword, which allows you to implicitly definea local variable. As you will see later in this book, implicit typing is extremely helpful, if not occasionally mandatory, when working with the LINQ technology set. You will wrap up this chapter by quickly examining the C# keywords and operators that allow you to control the flow of an application using various looping and decision constructs.<br \/>\n\u672c\u7ae0\u8fd8\u5c06\u7814\u7a76 C# var \u5173\u952e\u5b57\u7684\u4f5c\u7528\uff0c\u8be5\u5173\u952e\u5b57\u5141\u8bb8\u60a8\u9690\u5f0f\u5b9a\u4e49\u5c40\u90e8\u53d8\u91cf\u3002\u6b63\u5982\u60a8\u5c06\u5728\u672c\u4e66\u540e\u9762\u770b\u5230\u7684\u90a3\u6837\uff0c\u5728\u4f7f\u7528 LINQ \u6280\u672f\u96c6\u65f6\uff0c\u9690\u5f0f\u952e\u5165\u975e\u5e38\u6709\u7528\uff08\u5982\u679c\u4e0d\u662f\u5076\u5c14\u662f\u5fc5\u9700\u7684\uff09\u3002\u901a\u8fc7\u5feb\u901f\u68c0\u67e5 C# \u5173\u952e\u5b57\u548c\u8fd0\u7b97\u7b26\u6765\u7ed3\u675f\u672c\u7ae0\uff0c\u8fd9\u4e9b\u5173\u952e\u5b57\u548c\u8fd0\u7b97\u7b26\u5141\u8bb8\u60a8\u4f7f\u7528\u5404\u79cd\u5faa\u73af\u548c\u51b3\u7b56\u6784\u9020\u6765\u63a7\u5236\u5e94\u7528\u7a0b\u5e8f\u7684\u6d41\u3002<\/p>\n<h2>Breaking Down a Simple C# Program (Updated C# 10)<\/h2>\n<p>\u5206\u89e3\u7b80\u5355\u7684 C# \u7a0b\u5e8f\uff08\u66f4\u65b0\u7684 C# 10\uff09<\/p>\n<p>C# demands that all program logic be contained within a type definition (recall from Chapter 1 that type is a general term referring to a member of the set {class, interface, structure, enumeration, delegate}). Unlike many other languages, in C# it is not possible to create global functions or global points of data. Rather, all data members and all methods must be contained within a type definition. To get the ball rolling, create a new empty solution named Chapter3_AllProject.sln that contains a C# console application named SimpleCSharpApp.<br \/>\nC# \u8981\u6c42\u6240\u6709\u7a0b\u5e8f\u903b\u8f91\u90fd\u5305\u542b\u5728\u7c7b\u578b\u5b9a\u4e49\u4e2d\uff08\u56de\u60f3\u4e00\u4e0b\u7b2c 1 \u7ae0\uff0c\u7c7b\u578b\u662f\u4e00\u4e2a\u901a\u7528\u672f\u8bed\uff0c\u6307\u7684\u662f\u96c6\u5408 {\u7c7b\u3001\u63a5\u53e3\u3001\u7ed3\u6784\u3001\u679a\u4e3e\u3001\u59d4\u6258} \u7684\u6210\u5458\uff09\u3002 \u4e0e\u8bb8\u591a\u5176\u4ed6\u8bed\u8a00\u4e0d\u540c\uff0c\u5728 C# \u4e2d\u65e0\u6cd5\u521b\u5efa\u5168\u5c40\u51fd\u6570\u6216\u5168\u5c40\u6570\u636e\u70b9\u3002\u76f8\u53cd\uff0c\u6240\u6709\u6570\u636e\u6210\u5458\u548c\u6240\u6709\u65b9\u6cd5\u90fd\u5fc5\u987b\u5305\u542b\u5728\u7c7b\u578b\u5b9a\u4e49\u4e2d\u3002\u8981\u8ba9\u7403\u6eda\u52a8\uff0c\u8bf7\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a Chapter3_AllProject.sln \u7684\u65b0\u7a7a\u89e3\u51b3\u65b9\u6848\uff0c\u5176\u4e2d\u5305\u542b\u4e00\u4e2a\u540d\u4e3a SimpleCSharpApp \u7684 C# \u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u3002<\/p>\n<p>From Visual Studio, select the Blank Solution template on the \u201cCreate a new project\u201d screen. When the solution opens, right-click the solution in Solution Explorer and select Add \u27a4 New Project. Select \u201cC# console app\u201d from the templates, name it SimpleCSharpApp, and click Next. Select .NET 6.0 for the framework and then click Create.<br \/>\n\u4ece Visual Studio \u4e2d\uff0c\u5728\u201c\u521b\u5efa\u65b0\u9879\u76ee\u201d\u5c4f\u5e55\u4e0a\u9009\u62e9\u201c\u7a7a\u767d\u89e3\u51b3\u65b9\u6848\u201d\u6a21\u677f\u3002\u5f53\u89e3\u51b3\u65b9\u6848\u6253\u5f00\u65f6\uff0c\u5728\u201c\u89e3\u51b3\u65b9\u6848\u8d44\u6e90\u7ba1\u7406\u5668\u201d\u4e2d\u53f3\u952e\u5355\u51fb\u8be5\u89e3\u51b3\u65b9\u6848\uff0c\u7136\u540e\u9009\u62e9\u201c\u6dfb\u52a0\u201d\u27a4\u201c\u65b0\u5efa\u9879\u76ee\u201d\u3002\u4ece\u6a21\u677f\u4e2d\u9009\u62e9\u201cC# \u63a7\u5236\u53f0\u5e94\u7528\u201d\uff0c\u5c06\u5176\u547d\u540d\u4e3a SimpleCSharpApp\uff0c\u7136\u540e\u5355\u51fb\u201c\u4e0b\u4e00\u6b65\u201d\u3002\u4e3a\u6846\u67b6\u9009\u62e9\u201c.NET 6.0\u201d\uff0c\u7136\u540e\u5355\u51fb\u201c\u521b\u5efa\u201d\u3002<\/p>\n<p>To create a solution and console application and add that console application to the solution, from the command line (or the Visual Studio Code terminal window), execute the following:<br \/>\n\u82e5\u8981\u521b\u5efa\u89e3\u51b3\u65b9\u6848\u548c\u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u5e76\u5c06\u8be5\u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u6dfb\u52a0\u5230\u89e3\u51b3\u65b9\u6848\u4e2d\uff0c\u8bf7\u4ece\u547d\u4ee4\u884c\uff08\u6216 Visual Studio \u4ee3\u7801\u7ec8\u7aef\u7a97\u53e3\uff09\u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\uff1a<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ndotnet new sln -n Chapter3_AllProjects\ndotnet new console -lang c# -n SimpleCSharpApp -o .\\SimpleCSharpApp -f net6.0 \ndotnet sln .\\Chapter3_AllProjects.sln add .\\SimpleCSharpApp\n<\/pre>\n<\/p>\n<p>In the created project, you will see one file (named Program.cs) with one line of code.<br \/>\n\u5728\u521b\u5efa\u7684\u9879\u76ee\u4e2d\uff0c\u60a8\u5c06\u770b\u5230\u4e00\u4e2a\u5305\u542b\u4e00\u884c\u4ee3\u7801\u7684\u6587\u4ef6\uff08\u540d\u4e3a Program.cs\uff09\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nConsole.WriteLine(&quot;Hello, World!&quot;);\n<\/pre>\n<\/p>\n<p>If you are new to C#, this line seems pretty straightforward. It writes the message \u201cHello, World!\u201d to the standard console output window. Prior to C# 10, there was a lot more code required to achieve the same effect. When creating the same program in versions of C# prior to C# 10, you were required to write the following:<br \/>\n\u5982\u679c\u4f60\u4e0d\u719f\u6089 C#\uff0c\u8fd9\u4e00\u884c\u4f3c\u4e4e\u5f88\u7b80\u5355\u3002\u5b83\u5c06\u6d88\u606f\u201cHello\uff0c World\uff01\u201d\u5199\u5165\u6807\u51c6\u63a7\u5236\u53f0\u8f93\u51fa\u7a97\u53e3\u3002\u5728 C# 10 \u4e4b\u524d\uff0c\u9700\u8981\u66f4\u591a\u4ee3\u7801\u624d\u80fd\u8fbe\u5230\u76f8\u540c\u7684\u6548\u679c\u3002\u5728 C# 10 \u4e4b\u524d\u7684 C# \u7248\u672c\u4e2d\u521b\u5efa\u540c\u4e00\u7a0b\u5e8f\u65f6\uff0c\u9700\u8981\u7f16\u5199\u4ee5\u4e0b\u5185\u5bb9\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing System;\nnamespace SimpleCSharpApp\n{\n    class Program\n    {\n        static void Main(string&#x5B;] args)\n        {\n            Console.WriteLine(&quot;Hello World!&quot;);\n        }\n    }\n}\n<\/pre>\n<\/p>\n<p>The Console class is contained in the System namespace, and with the implicit global namespaces provided by .NET 6\/C# 10, the using System; statement is no longer needed. The next line creates a custom namespace (covered in Chapter 16) to wrap the Program class. Both the namespace and the Program class can be removed due to the top-level statement functionality introduced in C# 9 (covered shortly). That brings us back to the single line of code to write the message to the Console.<br \/>\n\u63a7\u5236\u53f0\u7c7b\u5305\u542b\u5728 System \u547d\u540d\u7a7a\u95f4\u4e2d\uff0c\u5e76\u4f7f\u7528 .NET 6\/C# 10 \u63d0\u4f9b\u7684\u9690\u5f0f\u5168\u5c40\u547d\u540d\u7a7a\u95f4\uff0cusing System; \u4e0d\u518d\u9700\u8981\u8bed\u53e5\u3002\u4e0b\u4e00\u884c\u521b\u5efa\u4e00\u4e2a\u81ea\u5b9a\u4e49\u547d\u540d\u7a7a\u95f4\uff08\u5728\u7b2c 16 \u7ae0\u4e2d\u4ecb\u7ecd\uff09\u6765\u5305\u88c5 Program \u7c7b\u3002\u7531\u4e8e C# 9 \u4e2d\u5f15\u5165\u7684\u9876\u7ea7\u8bed\u53e5\u529f\u80fd\uff08\u7a0d\u540e\u5c06\u4ecb\u7ecd\uff09\uff0c\u53ef\u4ee5\u5220\u9664\u547d\u540d\u7a7a\u95f4\u548c Program \u7c7b\u3002\u8fd9\u4f7f\u6211\u4eec\u56de\u5230\u5c06\u6d88\u606f\u5199\u5165\u63a7\u5236\u53f0\u7684\u5355\u884c\u4ee3\u7801\u3002<\/p>\n<p>For now, to cover some important variations of the entry point into C# applications, we will use the older (more verbose) style of code instead of the streamlined C# 10 version. Given this, update the Main() method of your Program class with the following code statements:<br \/>\n\u73b0\u5728\uff0c\u4e3a\u4e86\u4ecb\u7ecd C# \u5e94\u7528\u7a0b\u5e8f\u5165\u53e3\u70b9\u7684\u4e00\u4e9b\u91cd\u8981\u53d8\u4f53\uff0c\u6211\u4eec\u5c06\u4f7f\u7528\u8f83\u65e7\uff08\u66f4\u8be6\u7ec6\uff09\u7684\u4ee3\u7801\u6837\u5f0f\uff0c\u800c\u4e0d\u662f\u7b80\u5316\u7684 C# 10 \u7248\u672c\u3002\u9274\u4e8e\u6b64\uff0c\u4f7f\u7528\u4ee5\u4e0b\u4ee3\u7801\u8bed\u53e5\u66f4\u65b0 Program \u7c7b\u7684 Main\uff08\uff09 \u65b9\u6cd5\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nclass Program\n{\n    static void Main(string&#x5B;] args)\n    {\n        \/\/ Display a simple message to the user.\n        \/\/ \u5411\u7528\u6237\u663e\u793a\u4e00\u6761\u7b80\u5355\u7684\u6d88\u606f\u3002\n        Console.WriteLine(&quot;***** My First C# App *****&quot;);\n        Console.WriteLine(&quot;Hello World!&quot;);\n        Console.WriteLine();\n\n        \/\/ Wait for Enter key to be pressed before shutting down.\n        \/\/\u7b49\u5f85\u6309\u56de\u8f66\u952e\u540e\u518d\u5173\u95ed\u3002\n        Console.ReadLine();\n    }\n}\n<\/pre>\n<\/p>\n<blockquote><p>\n\u25a0 Note C# is a case-sensitive programming language. therefore, Main is not the same as main, and Readline is not the same as ReadLine. Be aware that all C# keywords are lowercase (e.g., public, lock, class, dynamic), while namespaces, types, and member names begin (by convention) with an initial capital letter and the first letter of any embedded words is capitalized (e.g., Console.WriteLine, System.Windows. MessageBox, System.Data.SqlClient). as a rule of thumb, whenever you receive a compiler error regarding \u201cundefined symbols,\u201d be sure to check your spelling and casing first!<br \/>\n\u6ce8\u610f C# \u662f\u4e00\u79cd\u533a\u5206\u5927\u5c0f\u5199\u7684\u7f16\u7a0b\u8bed\u8a00\u3002\u56e0\u6b64\uff0cMain \u4e0e main \u4e0d\u540c\uff0cReadline \u4e0e ReadLine \u4e5f\u4e0d\u76f8\u540c\u3002\u8bf7\u6ce8\u610f\uff0c\u6240\u6709 C# \u5173\u952e\u5b57\u90fd\u662f\u5c0f\u5199\u7684\uff08\u4f8b\u5982\uff0cpublic\u3001lock\u3001class\u3001dynamic\uff09\uff0c\u800c\u547d\u540d\u7a7a\u95f4\u3001\u7c7b\u578b\u548c\u6210\u5458\u540d\u79f0\uff08\u6309\u7167\u60ef\u4f8b\uff09\u4ee5\u9996\u5b57\u6bcd\u5927\u5199\u5b57\u6bcd\u5f00\u5934\u4efb\u4f55\u5d4c\u5165\u5355\u8bcd\u7684\u7b2c\u4e00\u4e2a\u5b57\u6bcd\u90fd\u662f\u5927\u5199\u7684\uff08\u4f8b\u5982\uff0cConsole.WriteLine\uff0cSystem.Windows\u3002MessageBox\uff0c System.Data.SqlClient\uff09\u3002\u6839\u636e\u7ecf\u9a8c\uff0c\u6bcf\u5f53\u60a8\u6536\u5230\u6709\u5173\u201c\u672a\u5b9a\u4e49\u7b26\u53f7\u201d\u7684\u7f16\u8bd1\u5668\u9519\u8bef\u65f6\uff0c\u8bf7\u52a1\u5fc5\u5148\u68c0\u67e5\u62fc\u5199\u548c\u5927\u5c0f\u5199\uff01\n<\/p><\/blockquote>\n<p>The previous code contains a definition for a class type that supports a single method named Main(). By default, the C# project templates that don\u2019t use top-level statements name the class containing the Main() method Program; however, you are free to change this if you so choose. Prior to C# 9.0, every executable C# application (console program, Windows desktop program, or Windows service) must contain a class defining a Main() method, which is used to signify the entry point of the application.<br \/>\n\u524d\u9762\u7684\u4ee3\u7801\u5305\u542b\u652f\u6301\u540d\u4e3a Main\uff08\uff09 \u7684\u5355\u4e2a\u65b9\u6cd5\u7684\u7c7b\u7c7b\u578b\u7684\u5b9a\u4e49\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u4e0d\u4f7f\u7528\u9876\u7ea7\u8bed\u53e5\u7684 C# \u9879\u76ee\u6a21\u677f\u547d\u540d\u5305\u542b Main\uff08\uff09 \u65b9\u6cd5\u7a0b\u5e8f\u7684\u7c7b;\u4f46\u662f\uff0c\u5982\u679c\u60a8\u613f\u610f\uff0c\u60a8\u53ef\u4ee5\u81ea\u7531\u66f4\u6539\u6b64\u8bbe\u7f6e\u3002\u5728 C# 9.0 \u4e4b\u524d\uff0c\u6bcf\u4e2a\u53ef\u6267\u884c\u6587\u4ef6C# \u5e94\u7528\u7a0b\u5e8f\uff08\u63a7\u5236\u53f0\u7a0b\u5e8f\u3001Windows \u684c\u9762\u7a0b\u5e8f\u6216 Windows \u670d\u52a1\uff09\u5fc5\u987b\u5305\u542b\u4e00\u4e2a\u5b9a\u4e49 Main\uff08\uff09 \u65b9\u6cd5\u7684\u7c7b\uff0c\u8be5\u65b9\u6cd5\u7528\u4e8e\u8868\u793a\u5e94\u7528\u7a0b\u5e8f\u7684\u5165\u53e3\u70b9\u3002<\/p>\n<p>Formally speaking, the class that defines the Main() method is termed the application object. It is possible for a single executable application to have more than one application object (which can be useful when performing unit tests), but then the compiler must know which Main() method should be used as the entry point. This can be done via the <StartupObject> element in the project file or via the Startup Object drop-down list box, located on the Application tab of the Visual Studio project properties window.<br \/>\n\u4ece\u5f62\u5f0f\u4e0a\u8bb2\uff0c\u5b9a\u4e49 Main\uff08\uff09 \u65b9\u6cd5\u7684\u7c7b\u79f0\u4e3a\u5e94\u7528\u7a0b\u5e8f\u5bf9\u8c61\u3002\u662f\u7684\u5355\u4e2a\u53ef\u6267\u884c\u5e94\u7528\u7a0b\u5e8f\u53ef\u80fd\u5177\u6709\u591a\u4e2a\u5e94\u7528\u7a0b\u5e8f\u5bf9\u8c61\uff08\u8fd9\u5728\u6267\u884c\u5355\u5143\u6d4b\u8bd5\u65f6\u5f88\u6709\u7528\uff09\uff0c\u4f46\u662f\u7f16\u8bd1\u5668\u5fc5\u987b\u77e5\u9053\u5e94\u4f7f\u7528\u54ea\u4e2a Main\uff08\uff09 \u65b9\u6cd5\u4f5c\u4e3a\u5165\u53e3\u70b9\u3002\u8fd9\u53ef\u4ee5\u901a\u8fc7\u9879\u76ee\u6587\u4ef6\u4e2d\u7684<StartupObject>\u5143\u7d20\u6216\u901a\u8fc7\u4f4d\u4e8eVisual Studio\u9879\u76ee\u5c5e\u6027\u7a97\u53e3\u7684\u201c\u5e94\u7528\u7a0b\u5e8f\u201d\u9009\u9879\u5361\u4e0a\u7684\u201c\u542f\u52a8\u5bf9\u8c61\u201d\u4e0b\u62c9\u5217\u8868\u6846\u6765\u5b8c\u6210\u3002<\/p>\n<p>Note that the signature of Main() is adorned with the static keyword, which will be examined in detail in Chapter 5. For the time being, simply understand that static members are scoped to the class level (rather than the object level) and can thus be invoked without the need to first create a new class instance.<br \/>\n\u8bf7\u6ce8\u610f\uff0cMain\uff08\uff09 \u7684\u7b7e\u540d\u88c5\u9970\u6709\u9759\u6001\u5173\u952e\u5b57\uff0c\u8fd9\u5c06\u5728\u7b2c 5 \u7ae0\u4e2d\u8be6\u7ec6\u7814\u7a76\u3002\u76ee\u524d\uff0c\u53ea\u9700\u7406\u89e3\u9759\u6001\u6210\u5458\u7684\u4f5c\u7528\u57df\u4e3a\u7c7b\u7ea7\u522b\uff08\u800c\u4e0d\u662f\u5bf9\u8c61\u7ea7\u522b\uff09\uff0c\u56e0\u6b64\u65e0\u9700\u5148\u521b\u5efa\u65b0\u7684\u7c7b\u5b9e\u4f8b\u5373\u53ef\u8c03\u7528\u3002<\/p>\n<p>In addition to the static keyword, this Main() method has a single parameter, which happens to be an array of strings (string[] args). Although you are not currently bothering to process this array, this parameter may contain any number of incoming command-line arguments (you will see how to access them momentarily). Finally, this Main() method has been set up with a void return value, meaning you do not explicitly define a return value using the return keyword before exiting the method scope.<br \/>\n\u9664\u4e86 static \u5173\u952e\u5b57\u4e4b\u5916\uff0c\u8fd9\u4e2a Main\uff08\uff09 \u65b9\u6cd5\u8fd8\u6709\u4e00\u4e2a\u53c2\u6570\uff0c\u5b83\u6070\u597d\u662f\u4e00\u4e2a\u5b57\u7b26\u4e32\u6570\u7ec4\uff08string[] args\uff09\u3002\u867d\u7136\u60a8\u76ee\u524d\u6ca1\u6709\u8d39\u5fc3\u5904\u7406\u6b64\u6570\u7ec4\uff0c\u4f46\u8fd9\u53c2\u6570\u53ef\u80fd\u5305\u542b\u4efb\u610f\u6570\u91cf\u7684\u4f20\u5165\u547d\u4ee4\u884c\u53c2\u6570\uff08\u60a8\u5c06\u7acb\u5373\u4e86\u89e3\u5982\u4f55\u8bbf\u95ee\u5b83\u4eec\uff09\u3002\u6700\u540e\uff0c\u8fd9\u4e2a Main\uff08\uff09 \u65b9\u6cd5\u5df2\u7ecf\u8bbe\u7f6e\u4e86\u4e00\u4e2a void \u8fd4\u56de\u503c\uff0c\u8fd9\u610f\u5473\u7740\u5728\u9000\u51fa\u65b9\u6cd5\u8303\u56f4\u4e4b\u524d\uff0c\u60a8\u4e0d\u4f1a\u4f7f\u7528 return \u5173\u952e\u5b57\u663e\u5f0f\u5b9a\u4e49\u8fd4\u56de\u503c\u3002<\/p>\n<p>The logic of the Program class is within Main(). Here, you make use of the Console class, which is defined within the System namespace. Among its set of members is the static WriteLine(), which, as you might assume, sends a text string and carriage return to the standard output. You also make a call to Console.ReadLine() to ensure the command prompt launched by the Visual Studio IDE remains visible. When running .NET Core Console apps with Visual Studio (in either Debug or Release mode), the console window remains visible by default. This behavior can be changed by enabling the setting \u201cAutomatically close the console when debugging stops\u201d found under Tools \u27a4 Options \u27a4 Debugging. The Console.ReadLine() method is there to keep the window open if the program is executed from Windows Explorer by double- clicking the product <em>.exe file. You will learn more about the System.Console class shortly.<br \/>\nProgram \u7c7b\u7684\u903b\u8f91\u5728 Main\uff08\uff09 \u4e2d\u3002\u5728\u8fd9\u91cc\uff0c\u60a8\u5c06\u4f7f\u7528\u5728 System \u547d\u540d\u7a7a\u95f4\u4e2d\u5b9a\u4e49\u7684 Console \u7c7b\u3002\u5728\u5176\u6210\u5458\u96c6\u4e2d\u662f\u9759\u6001 WriteLine\uff08\uff09\uff0c\u6b63\u5982\u60a8\u53ef\u80fd\u5047\u8bbe\u7684\u90a3\u6837\uff0c\u5b83\u5c06\u6587\u672c\u5b57\u7b26\u4e32\u548c\u56de\u8f66\u7b26\u53d1\u9001\u5230\u6807\u51c6\u8f93\u51fa\u3002\u60a8\u8fd8\u53ef\u4ee5\u8c03\u7528\u63a7\u5236\u53f0\u3002ReadLine\uff08\uff09 \u6765\u786e\u4fdd Visual Studio IDE \u542f\u52a8\u7684\u547d\u4ee4\u63d0\u793a\u7b26\u4ecd\u7136\u53ef\u89c1\u3002\u4f7f\u7528 Visual Studio \u8fd0\u884c .NET Core \u63a7\u5236\u53f0\u5e94\u7528\uff08\u5728\u8c03\u8bd5\u6216\u53d1\u5e03\u6a21\u5f0f\u4e0b\uff09\u65f6\uff0c\u63a7\u5236\u53f0\u7a97\u53e3\u9ed8\u8ba4\u4fdd\u6301\u53ef\u89c1\u3002\u53ef\u4ee5\u901a\u8fc7\u542f\u7528\u201c\u5de5\u5177\u201d\u27a4\u201c\u9009\u9879\u201d\u27a4\u201c\u8c03\u8bd5\u201d\u4e0b\u7684\u201c\u8c03\u8bd5\u505c\u6b62\u65f6\u81ea\u52a8\u5173\u95ed\u63a7\u5236\u53f0\u201d\u8bbe\u7f6e\u6765\u66f4\u6539\u6b64\u884c\u4e3a\u3002\u5982\u679c\u901a\u8fc7\u53cc\u51fb\u4ea7\u54c1 <\/em>.exe \u6587\u4ef6\u4ece Windows \u8d44\u6e90\u7ba1\u7406\u5668\u6267\u884c\u7a0b\u5e8f\uff0c\u5219 Console.ReadLine\uff08\uff09 \u65b9\u6cd5\u53ef\u4ee5\u4fdd\u6301\u7a97\u53e3\u6253\u5f00\u3002\u60a8\u5c06\u5f88\u5feb\u4e86\u89e3\u6709\u5173 System.Console \u7c7b\u7684\u66f4\u591a\u4fe1\u606f\u3002v<\/p>\n<h2>Using Variations of the Main() Method (Updated 7.1)<\/h2>\n<p>\u4f7f\u7528 main\uff08\uff09 \u65b9\u6cd5\u7684\u53d8\u4f53\uff08\u66f4\u65b0 7.1\uff09<\/p>\n<p>By default, the .NET console project template will generate a Main() method that has a void return value and an array of string types as the single input parameter. This is not the only possible form of Main(), however. It is permissible to construct your application\u2019s entry point using any of the following signatures (assuming it is contained within a C# class or structure definition):<br \/>\n\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c.NET \u63a7\u5236\u53f0\u9879\u76ee\u6a21\u677f\u5c06\u751f\u6210\u4e00\u4e2a Main\uff08\uff09 \u65b9\u6cd5\uff0c\u8be5\u65b9\u6cd5\u5177\u6709 void \u8fd4\u56de\u503c\u548c\u5b57\u7b26\u4e32\u7c7b\u578b\u6570\u7ec4\u4f5c\u4e3a\u5355\u4e2a\u8f93\u5165\u53c2\u6570\u3002\u7136\u800c\uff0c\u8fd9\u5e76\u4e0d\u662f Main\uff08\uff09 \u7684\u552f\u4e00\u53ef\u80fd\u5f62\u5f0f\u3002\u5141\u8bb8\u4f7f\u7528\u4ee5\u4e0b\u4efb\u4f55\u7b7e\u540d\u6784\u9020\u5e94\u7528\u7a0b\u5e8f\u7684\u5165\u53e3\u70b9\uff08\u5047\u8bbe\u5b83\u5305\u542b\u5728 C# \u7c7b\u6216\u7ed3\u6784\u5b9a\u4e49\u4e2d\uff09\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ int return type, array of strings as the parameter.\n\/\/ int \u8fd4\u56de\u7c7b\u578b\uff0c\u5b57\u7b26\u4e32\u6570\u7ec4\u4f5c\u4e3a\u53c2\u6570\u3002\nstatic int Main(string&#x5B;] args)\n{\n    \/\/ Must return a value before exiting!\n    \/\/ \u9000\u51fa\u524d\u5fc5\u987b\u8fd4\u56de\u4e00\u4e2a\u503c\uff01return 0;\n    return 0;\n}\n<\/pre>\n<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ No return type, no parameters.\n\/\/ \u6ca1\u6709\u8fd4\u56de\u7c7b\u578b\uff0c\u6ca1\u6709\u53c2\u6570\u3002\nstatic void Main()\n{\n}\n<\/pre>\n<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ int return type, no parameters.\nstatic int Main()\n{\n    \/\/ Must return a value before exiting!\n    return 0;\n}\n<\/pre>\n<\/p>\n<p>With the release of C# 7.1, the Main() method can be asynchronous. Async programming is covered in Chapter 15, but for now realize there are four additional signatures.<br \/>\n\u968f\u7740 C# 7.1 \u7684\u53d1\u5e03\uff0cMain\uff08\uff09 \u65b9\u6cd5\u53ef\u4ee5\u662f\u5f02\u6b65\u7684\u3002\u5f02\u6b65\u7f16\u7a0b\u5728\u7b2c15\u7ae0\u4e2d\u4ecb\u7ecd\uff0c\u4f46\u73b0\u5728\u610f\u8bc6\u5230\u8fd8\u6709\u56db\u4e2a\u989d\u5916\u7684\u7b7e\u540d\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic Task Main() \nstatic Task&lt;int&gt; Main()\nstatic Task Main(string&#x5B;]) \nstatic Task&lt;int&gt; Main(string&#x5B;])\n<\/pre>\n<\/p>\n<blockquote><p>\n\u25a0 Note the Main() method may also be defined as public as opposed to private. note that private is assumed if you do not supply a specific access modifier. access modifiers are covered in detail in Chapter 5.<br \/>\n\u6ce8\u610f Main\uff08\uff09 \u65b9\u6cd5\u4e5f\u53ef\u4ee5\u5b9a\u4e49\u4e3a\u516c\u5171\u7684\uff0c\u800c\u4e0d\u662f\u79c1\u6709\u7684\u3002 \u8bf7\u6ce8\u610f\uff0c\u5982\u679c\u672a\u63d0\u4f9b\u7279\u5b9a\u7684\u8bbf\u95ee\u4fee\u9970\u7b26\uff0c\u5219\u5047\u5b9a\u4e3a\u79c1\u6709\u3002 \u8bbf\u95ee\u4fee\u9970\u7b26\u5728\u7b2c 5 \u7ae0\u4e2d\u6709\u8be6\u7ec6\u4ecb\u7ecd\u3002\n<\/p><\/blockquote>\n<p>Obviously, your choice of how to construct Main() will be based on three questions. First, do you want to return a value to the system when Main() has completed and your program terminates? If so, you need to return an int data type rather than void. Second, do you need to process any user-supplied, command- line parameters? If so, they will be stored in the array of strings. Lastly, do you need to call asynchronous code from the Main() method? We\u2019ll examine the first two options in more detail after introducing top-level statements. The async options will be covered in Chapter 15.<br \/>\n\u663e\u7136\uff0c\u4f60\u9009\u62e9\u5982\u4f55\u6784\u9020 Main\uff08\uff09 \u5c06\u57fa\u4e8e\u4e09\u4e2a\u95ee\u9898\u3002\u9996\u5148\uff0c\u662f\u5426\u8981\u5728 Main\uff08\uff09 \u5b8c\u6210\u5e76\u4e14\u7a0b\u5e8f\u7ec8\u6b62\u65f6\u5411\u7cfb\u7edf\u8fd4\u56de\u4e00\u4e2a\u503c\uff1f\u5982\u679c\u662f\u8fd9\u6837\uff0c\u5219\u9700\u8981\u8fd4\u56de int \u6570\u636e\u7c7b\u578b\u800c\u4e0d\u662f void\u3002\u5176\u6b21\uff0c\u662f\u5426\u9700\u8981\u5904\u7406\u4efb\u4f55\u7528\u6237\u63d0\u4f9b\u7684\u547d\u4ee4\u884c\u53c2\u6570\uff1f\u5982\u679c\u662f\u8fd9\u6837\uff0c\u5b83\u4eec\u5c06\u5b58\u50a8\u5728\u5b57\u7b26\u4e32s \u6570\u7ec4\u4e2d\u3002\u6700\u540e\uff0c\u662f\u5426\u9700\u8981\u4ece Main\uff08\uff09 \u65b9\u6cd5\u8c03\u7528\u5f02\u6b65\u4ee3\u7801\uff1f\u5728\u5f15\u5165\u9876\u7ea7\u8bed\u53e5\u540e\uff0c\u6211\u4eec\u5c06\u66f4\u8be6\u7ec6\u5730\u7814\u7a76\u524d\u4e24\u4e2a\u9009\u9879\u3002\u5f02\u6b65\u9009\u9879\u5c06\u5728\u7b2c 15 \u7ae0\u4e2d\u4ecb\u7ecd\u3002<\/p>\n<h2>Using Top-Level Statements (New 9.0)<\/h2>\n<p>\u4f7f\u7528\u9876\u7ea7\u8bed\u53e5\uff08\u65b0 9.0\uff09<\/p>\n<p>While it is true that prior to C# 9.0, all C# .NET Core applications must have a Main() method, C# 9.0 introduced top-level statements, which eliminate the need for much of the ceremony around the C# application\u2019s entry point. Both the class (Program) and Main() methods can be removed. To see this in action, update the Program.cs class to match the following:<br \/>\n\u867d\u7136\u5728 C# 9.0 \u4e4b\u524d\uff0c\u6240\u6709 C# .NET Core \u5e94\u7528\u7a0b\u5e8f\u90fd\u5fc5\u987b\u5177\u6709 Main\uff08\uff09 \u65b9\u6cd5\uff0c\u4f46 C# 9.0 \u5f15\u5165\u4e86\u9876\u7ea7\u8bed\u53e5\uff0c\u8fd9\u6d88\u9664\u4e86\u56f4\u7ed5 C# \u5e94\u7528\u7a0b\u5e8f\u5165\u53e3\u70b9\u8fdb\u884c\u5927\u90e8\u5206\u4eea\u5f0f\u7684\u9700\u8981\u3002\u7c7b \uff08Program\uff09 \u548c Main\uff08\uff09 \u65b9\u6cd5\u90fd\u53ef\u4ee5\u5220\u9664\u3002\u82e5\u8981\u67e5\u770b\u6b64\u64cd\u4f5c\u7684\u5b9e\u9645\u6548\u679c\uff0c\u8bf7\u66f4\u65b0 Program.cs \u7c7b\u4ee5\u5339\u914d\u4ee5\u4e0b\u5185\u5bb9\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Display a simple message to the user.\n\/\/ \u5411\u7528\u6237\u663e\u793a\u4e00\u6761\u7b80\u5355\u7684\u6d88\u606f\u3002\nConsole.WriteLine(&quot;***** My First C# App *****&quot;);\nConsole.WriteLine(&quot;Hello World!&quot;);\nConsole.WriteLine();\n\n\/\/ Wait for Enter key to be pressed before shutting down.\n\/\/ \u7b49\u5f85\u6309\u56de\u8f66\u952e\u540e\u518d\u5173\u95ed\u3002\nConsole.ReadLine();\n<\/pre>\n<\/p>\n<p>You will see that when you run the program, you get the same result! There are some rules around using top-level statements:<br \/>\n\u60a8\u5c06\u770b\u5230\uff0c\u5f53\u60a8\u8fd0\u884c\u8be5\u7a0b\u5e8f\u65f6\uff0c\u60a8\u4f1a\u5f97\u5230\u76f8\u540c\u7684\u7ed3\u679c\uff01\u4f7f\u7528\u9876\u7ea7\u8bed\u53e5\u6709\u4e00\u4e9b\u89c4\u5219\uff1a<\/p>\n<ul>\n<li>\nOnly one file in the application can use top-level statements.<br \/>\n\u5e94\u7528\u7a0b\u5e8f\u4e2d\u53ea\u6709\u4e00\u4e2a\u6587\u4ef6\u53ef\u4ee5\u4f7f\u7528\u9876\u7ea7\u8bed\u53e5\u3002\n<\/li>\n<li>\nWhen using top-level statements, the program cannot have a declared entry point.<br \/>\n\u4f7f\u7528\u9876\u7ea7\u8bed\u53e5\u65f6\uff0c\u7a0b\u5e8f\u4e0d\u80fd\u5177\u6709\u58f0\u660e\u7684\u5165\u53e3\u70b9\u3002\n<\/li>\n<li>\nThe top-level statements cannot be enclosed in a namespace.<br \/>\n\u9876\u7ea7\u8bed\u53e5\u4e0d\u80fd\u5305\u542b\u5728\u547d\u540d\u7a7a\u95f4\u4e2d\u3002\n<\/li>\n<li>\nTop-level statements still access a string array of args.<br \/>\n\u9876\u7ea7\u8bed\u53e5\u4ecd\u8bbf\u95ee\u53c2\u6570\u7684\u5b57\u7b26\u4e32\u6570\u7ec4\u3002\n<\/li>\n<li>\nTop-level statements return an application code (see the next section) by using a return.<br \/>\n\u9876\u7ea7\u8bed\u53e5\u4f7f\u7528\u8fd4\u56de\u5e94\u7528\u7a0b\u5e8f\u4ee3\u7801\uff08\u8bf7\u53c2\u9605\u4e0b\u4e00\u8282\uff09\u3002\n<\/li>\n<li>\nFunctions that would have been declared in the Program class become local functions for the top-level statements. (Local functions are covered in Chapter 4.)<br \/>\n\u672c\u5e94\u5728 Program \u7c7b\u4e2d\u58f0\u660e\u7684\u51fd\u6570\u5c06\u6210\u4e3a\u9876\u7ea7\u8bed\u53e5\u7684\u672c\u5730\u51fd\u6570\u3002\uff08\u672c\u7ae0\u4ecb\u7ecd\u4e86\u672c\u5730\u51fd\u6570 4.\uff09\n<\/li>\n<li>\nThe top-level statements compile to a class named Program, allowing for the addition of a partial Program class to hold regular methods. Partial classes are covered in Chapter 5.<br \/>\n\u9876\u7ea7\u8bed\u53e5\u7f16\u8bd1\u4e3a\u540d\u4e3a Program \u7684\u7c7b\uff0c\u5141\u8bb8\u6dfb\u52a0\u5206\u90e8 Program \u7c7b\u6765\u4fdd\u5b58\u5e38\u89c4\u65b9\u6cd5\u3002\u7b2c5\u7ae0\u4ecb\u7ecd\u4e86\u90e8\u5206\u7c7b\u3002\n<\/li>\n<li>\nAdditional types can be declared after all top-level statements. Any types declared before the end of the top-level statements will result in a compilation error.<br \/>\n\u53ef\u4ee5\u5728\u6240\u6709\u9876\u7ea7\u8bed\u53e5\u4e4b\u540e\u58f0\u660e\u5176\u4ed6\u7c7b\u578b\u3002\u5728\u9876\u7ea7\u8bed\u53e5\u672b\u5c3e\u58f0\u660e\u7684\u4efb\u4f55\u7c7b\u578b\u90fd\u5c06\u5bfc\u81f4\u7f16\u8bd1\u9519\u8bef\u3002\n<\/li>\n<\/ul>\n<p>Behind the scenes, the compiler fills in the blanks. Examining the generated IL for the updated code, you will see the following TypeDef for the entry point into the application:<br \/>\n\u5728\u5e55\u540e\uff0c\u7f16\u8bd1\u5668\u586b\u8865\u7a7a\u767d\u3002\u68c0\u67e5\u751f\u6210\u7684 IL \u4ee5\u83b7\u53d6\u66f4\u65b0\u7684\u4ee3\u7801\uff0c\u60a8\u5c06\u770b\u5230\u5e94\u7528\u7a0b\u5e8f\u7684\u5165\u53e3\u70b9\u7684\u4ee5\u4e0b TypeDef\uff1a<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/\/ TypeDef #1 (02000002)\n\/\/ -------------------------------------------------------\n\/\/ TypDefName: &lt;Program&gt;$ (02000002)\n\/\/ Flags : &#x5B;NotPublic] &#x5B;AutoLayout] &#x5B;Class] &#x5B;Abstract] &#x5B;Sealed] &#x5B;AnsiClass] &#x5B;BeforeFieldInit] (00100180)\n\/\/ Extends : 0100000D &#x5B;TypeRef] System.Object\n\/\/ Method #1 (06000001) &#x5B;ENTRYPOINT]\n\/\/ -------------------------------------------------------\n\/\/ MethodName: &lt;Main&gt;$ (06000001)\nCompare that to the TypeDef for the entry point from Chapter 1:\n\/\/ TypeDef #1 (02000002)\n\/\/ -------------------------------------------------------\n\/\/ TypDefName: CalculatorExamples.Program (02000002)\n\/\/ Flags : &#x5B;NotPublic] &#x5B;AutoLayout] &#x5B;Class] &#x5B;AnsiClass] &#x5B;BeforeFieldInit] (00100000)\n\/\/ Extends : 0100000C &#x5B;TypeRef] System.Object\n\/\/ Method #1 (06000001) &#x5B;ENTRYPOINT]\n\/\/ -------------------------------------------------------\n\/\/ MethodName: Main (06000001)\n<\/pre>\n<\/p>\n<p>Notice for the example from Chapter 1, the TypDefName value is shown as the namespace (CalculatorExamples) plus the class name (Program), and the MethodName value is Main. In the updated example using top-level statements, the compiler has filled in the values of <Program>$ for the TypDefName and <Main>$ for the method name.<br \/>\n\u8bf7\u6ce8\u610f\uff0c\u5bf9\u4e8e\u7b2c 1 \u7ae0\u4e2d\u7684\u793a\u4f8b\uff0cTypDefName \u503c\u663e\u793a\u4e3a\u547d\u540d\u7a7a\u95f4\uff08\u8ba1\u7b97\u5668\u793a\u4f8b\uff09\u52a0\u4e0a\u7c7b\u540d\uff08\u7a0b\u5e8f\uff09\uff0cMethodName \u503c\u663e\u793a\u4e3a Main\u3002\u5728\u4f7f\u7528\u9876\u7ea7\u8bed\u53e5\u7684\u66f4\u65b0\u793a\u4f8b\u4e2d\uff0c\u7f16\u8bd1\u5668\u4e3aTypDefName\u586b\u5145\u4e86<Program>$\u7684\u503c\uff0c\u4e3a\u65b9\u6cd5\u540d\u79f0\u586b\u5199\u4e86<Main>$\u7684\u503c\u3002<\/p>\n<h2>Specifying an Application Error Code (Updated 9.0)<\/h2>\n<p>\u6307\u5b9a\u5e94\u7528\u7a0b\u5e8f\u9519\u8bef\u4ee3\u7801\uff089.0 \u66f4\u65b0\uff09<\/p>\n<p>While a vast majority of your Main() methods (or top-level statements) will return void as the return value, the ability to return an int (or Task<int>) keeps C# consistent with other C-based languages. By convention, returning the value 0 indicates the program has terminated successfully, while another value (such as -1) represents an error condition (be aware that the value 0 is automatically returned, even if you construct a Main() method prototyped to return void).<br \/>\n\u867d\u7136\u7edd\u5927\u591a\u6570 Main\uff08\uff09 \u65b9\u6cd5\uff08\u6216\u9876\u7ea7\u8bed\u53e5\uff09\u5c06\u8fd4\u56de void \u4f5c\u4e3a\u8fd4\u56de\u503c\uff0c\u4f46\u8fd4\u56de int\uff08\u6216 Task<int>\uff09\u7684\u80fd\u529b\u4f7f C# \u4e0e\u5176\u4ed6\u57fa\u4e8e C \u7684\u8bed\u8a00\u4fdd\u6301\u4e00\u81f4\u3002\u6309\u7167\u60ef\u4f8b\uff0c\u8fd4\u56de\u503c 0 \u8868\u793a\u7a0b\u5e8f\u5df2\u6210\u529f\u7ec8\u6b62\uff0c\u800c\u53e6\u4e00\u4e2a\u503c\uff08\u5982 -1\uff09\u8868\u793a\u9519\u8bef\u6761\u4ef6\uff08\u8bf7\u6ce8\u610f\uff0c\u503c 0 \u4f1a\u81ea\u52a8\u8fd4\u56de\uff0c\u5373\u4f7f\u60a8\u6784\u9020\u4e86\u4e00\u4e2a\u539f\u578b\u5316\u4e3a\u8fd4\u56de void \u7684 Main\uff08\uff09 \u65b9\u6cd5\uff09\u3002<\/p>\n<p>When using top-level statements (and therefore no Main() method), if the executing code returns an integer, that is the return code. If nothing is explicitly returned, it still returns 0, as with explicitly using a Main() method.<br \/>\n\u5f53\u4f7f\u7528\u9876\u7ea7\u8bed\u53e5\uff08\u56e0\u6b64\u6ca1\u6709 Main\uff08\uff09 \u65b9\u6cd5\uff09\u65f6\uff0c\u5982\u679c\u6267\u884c\u4ee3\u7801\u8fd4\u56de\u4e00\u4e2a\u6574\u6570\uff0c\u90a3\u5c31\u662f\u8fd4\u56de\u4ee3\u7801\u3002\u5982\u679c\u672a\u663e\u5f0f\u8fd4\u56de\u4efb\u4f55\u5185\u5bb9\uff0c\u5b83\u4ecd\u8fd4\u56de 0\uff0c\u5c31\u50cf\u663e\u5f0f\u4f7f\u7528 Main\uff08\uff09 \u65b9\u6cd5\u4e00\u6837\u3002<\/p>\n<p>On the Windows operating system, an application\u2019s return value is stored within a system environment variable named %ERRORLEVEL%. If you were to create an application that programmatically launches another executable (a topic examined in Chapter 18), you can obtain the value of %ERRORLEVEL% using the ExitCode property of the launched process.<br \/>\n\u5728 Windows \u64cd\u4f5c\u7cfb\u7edf\u4e0a\uff0c\u5e94\u7528\u7a0b\u5e8f\u7684\u8fd4\u56de\u503c\u5b58\u50a8\u5728\u540d\u4e3a %ERRORLEVEL% \u7684\u7cfb\u7edf\u73af\u5883\u53d8\u91cf\u4e2d\u3002\u5982\u679c\u8981\u521b\u5efa\u4e00\u4e2a\u4ee5\u7f16\u7a0b\u65b9\u5f0f\u542f\u52a8\u53e6\u4e00\u4e2a\u53ef\u6267\u884c\u6587\u4ef6\u7684\u5e94\u7528\u7a0b\u5e8f\uff08\u7b2c 18 \u7ae0\u4e2d\u4ecb\u7ecd\u7684\u4e3b\u9898\uff09\uff0c\u5219\u53ef\u4ee5\u4f7f\u7528\u542f\u52a8\u7684\u8fdb\u7a0b\u7684 ExitCode \u5c5e\u6027\u83b7\u53d6 %ERRORLEVEL% \u7684\u503c\u3002<\/p>\n<p>Given that an application\u2019s return value is passed to the system at the time the application terminates, it is obviously not possible for an application to obtain and display its final error code while running.However, to illustrate how to view this error level upon program termination, begin by updating the top-level statements, as follows:<br \/>\n\u5047\u8bbe\u5e94\u7528\u7a0b\u5e8f\u7684\u8fd4\u56de\u503c\u5728\u5e94\u7528\u7a0b\u5e8f\u7ec8\u6b62\u65f6\u4f20\u9012\u7ed9\u7cfb\u7edf\uff0c\u5219\u5e94\u7528\u7a0b\u5e8f\u663e\u7136\u4e0d\u53ef\u80fd\u5728\u8fd0\u884c\u65f6\u83b7\u53d6\u5e76\u663e\u793a\u5176\u6700\u7ec8\u9519\u8bef\u4ee3\u7801\u3002\u4f46\u662f\uff0c\u4e3a\u4e86\u8bf4\u660e\u5982\u4f55\u5728\u7a0b\u5e8f\u7ec8\u6b62\u65f6\u67e5\u770b\u6b64\u9519\u8bef\u7ea7\u522b\uff0c\u8bf7\u9996\u5148\u66f4\u65b0\u9876\u7ea7\u8bed\u53e5\uff0c\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Note we are explicitly returning an int, rather than void.\n\/\/ \u8bf7\u6ce8\u610f\uff0c\u6211\u4eec\u663e\u5f0f\u8fd4\u56de\u4e00\u4e2a int\uff0c\u800c\u4e0d\u662f void\u3002\n\/\/ Display a message and wait for Enter key to be pressed.\n\/\/ \u663e\u793a\u4e00\u6761\u6d88\u606f\u5e76\u7b49\u5f85\u6309\u4e0b Enter \u952e\u3002\nConsole.WriteLine(&quot;***** My First C# App *****&quot;);\nConsole.WriteLine(&quot;Hello World!&quot;);\nConsole.WriteLine();\nConsole.ReadLine();\n<\/pre>\n<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/\/ Return an arbitrary error code. \n\/\/ \u8fd4\u56de\u4efb\u610f\u9519\u8bef\u4ee3\u7801\u3002\u8fd4\u56de -1;\nreturn -1;\n<\/pre>\n<\/p>\n<p>If the program is still using a Main() method as the entry point, change the method signature to return int instead of void, as follows:<br \/>\n\u5982\u679c\u7a0b\u5e8f\u4ecd\u5728\u4f7f\u7528 Main\uff08\uff09 \u65b9\u6cd5\u4f5c\u4e3a\u5165\u53e3\u70b9\uff0c\u8bf7\u5c06\u65b9\u6cd5\u7b7e\u540d\u66f4\u6539\u4e3a\u8fd4\u56deint \u800c\u4e0d\u662f void\uff0c\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic int Main()\n{\n...\n}\n<\/pre>\n<\/p>\n<p>Now let\u2019s capture the return value of the program with the help of a batch file. Using Windows Explorer, navigate to the folder containing your project file (e.g., C:\\SimpleCSharpApp) and add a new text file (named SimpleCSharpApp.cmd) to that folder. Update the contents of the folder to the following (if you have not authored <em>.cmd files before, do not concern yourself with the details):<br \/>\n\u73b0\u5728\u8ba9\u6211\u4eec\u501f\u52a9\u6279\u5904\u7406\u6587\u4ef6\u6355\u83b7\u7a0b\u5e8f\u7684\u8fd4\u56de\u503c\u3002\u4f7f\u7528 Windows \u8d44\u6e90\u7ba1\u7406\u5668\uff0c\u5bfc\u822a\u5230\u5305\u542b\u9879\u76ee\u6587\u4ef6\u7684\u6587\u4ef6\u5939\uff08\u4f8b\u5982 C\uff1a\\SimpleCSharpApp\uff09\uff0c\u5e76\u5c06\u65b0\u7684\u6587\u672c\u6587\u4ef6\uff08\u540d\u4e3a SimpleCSharpApp.cmd\uff09\u6dfb\u52a0\u5230\u8be5\u6587\u4ef6\u5939\u3002 \u5c06\u6587\u4ef6\u5939\u7684\u5185\u5bb9\u66f4\u65b0\u4e3a\u4ee5\u4e0b\u5185\u5bb9\uff08\u5982\u679c\u60a8\u4ee5\u524d\u6ca1\u6709\u521b\u4f5c\u8fc7 <\/em>.cmd \u6587\u4ef6\uff0c\u8bf7\u4e0d\u8981\u5173\u5fc3\u8be6\u7ec6\u4fe1\u606f\uff09\uff1a<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n@echo off\nrem A batch file for SimpleCSharpApp.exe\nrem which captures the app's return value.\ndotnet run\n@if &quot;%ERRORLEVEL%&quot; == &quot;0&quot; goto success\n\n:fail\n    echo This application has failed!\n    echo return value = %ERRORLEVEL%\n    goto end\n:success\n    echo This application has succeeded!\n    echo return value = %ERRORLEVEL%\n    goto end\n:end\necho All Done.\n<\/pre>\n<\/p>\n<p>At this point, open a command prompt (or use the Visual Studio Code terminal) and navigate to the folder containing your new <em>.cmd file. Execute the file by typing its name and pressing the Enter key. You should find the output shown next, given that your top-level statements (or Main() method) return -1. Had the top-level statements (or Main() method) returned 0, you would see the message \u201cThis application has succeeded!\u201d print to the console.<br \/>\n\u6b64\u65f6\uff0c\u6253\u5f00\u547d\u4ee4\u63d0\u793a\u7b26\uff08\u6216\u4f7f\u7528 Visual Studio \u4ee3\u7801\u7ec8\u7aef\uff09\u5e76\u5bfc\u822a\u5230\u5305\u542b\u65b0 <\/em>.cmd \u6587\u4ef6\u7684\u6587\u4ef6\u5939\u3002\u901a\u8fc7\u952e\u5165\u6587\u4ef6\u540d\u79f0\u5e76\u6309 Enter \u952e\u6765\u6267\u884c\u6587\u4ef6\u3002\u60a8\u5e94\u8be5\u627e\u5230\u63a5\u4e0b\u6765\u663e\u793a\u7684\u8f93\u51fa\uff0c\u56e0\u4e3a\u60a8\u7684\u9876\u7ea7\u8bed\u53e5\uff08\u6216 Main\uff08\uff09 \u65b9\u6cd5\uff09\u8fd4\u56de -1\u3002\u5982\u679c\u9876\u7ea7\u8bed\u53e5\uff08\u6216 Main\uff08\uff09 \u65b9\u6cd5\uff09\u8fd4\u56de 0\uff0c\u60a8\u5c06\u770b\u5230\u6d88\u606f\u201c\u6b64\u5e94\u7528\u7a0b\u5e8f\u5df2\u6210\u529f\uff01<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n***** My First C# App ***** \n\nHello World!\n\nThis application has failed! Return value = -1\nAll Done.\n<\/pre>\n<\/p>\n<p>The PowerShell equivalent of the preceding <em>.cmd file is as follows:<br \/>\n\u524d\u9762\u7684 <\/em>.cmd \u6587\u4ef6\u7684 PowerShell \u7b49\u6548\u9879\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ndotnet run\nif ($LastExitCode -eq 0) {\n    Write-Host &quot;This application has succeeded!&quot;\n} else\n{\n    Write-Host &quot;This application has failed!&quot;\n}\nWrite-Host &quot;All Done.&quot;\n<\/pre>\n<\/p>\n<p>To run this, type PowerShell into the Visual Studio Code terminal and then execute the script by typing this:<br \/>\n\u82e5\u8981\u8fd0\u884c\u6b64\u547d\u4ee4\uff0c\u8bf7\u5728 Visual Studio Code \u7ec8\u7aef\u4e2d\u952e\u5165 PowerShell\uff0c\u7136\u540e\u901a\u8fc7\u952e\u5165\u4ee5\u4e0b\u547d\u4ee4\u6765\u6267\u884c\u811a\u672c\uff1a<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n.\\SimpleCSharpApp.ps1\n<\/pre>\n<\/p>\n<p>You will see the following in the terminal window:<br \/>\n\u60a8\u5c06\u5728\u7ec8\u7aef\u7a97\u53e3\u4e2d\u770b\u5230\u4ee5\u4e0b\u5185\u5bb9\uff1a<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n***** My First C# App ***** \nHello World!\n\nThis application has failed! All Done.\n<\/pre>\n<\/p>\n<blockquote><p>\n\u25a0 Note  if you receive a security policy error when running the powershell script, you can set the policy to allow unsigned local scripts by executing the following command in powershell:set-executionpolicy -executionpolicy remotesigned -scope currentuser<br \/>\n\u6ce8\u610f \u5982\u679c\u5728\u8fd0\u884c powershell \u811a\u672c\u65f6\u6536\u5230\u5b89\u5168\u7b56\u7565\u9519\u8bef\uff0c\u53ef\u4ee5\u901a\u8fc7\u5728 powershell \u4e2d\u6267\u884c\u4ee5\u4e0b\u547d\u4ee4\u5c06\u7b56\u7565\u8bbe\u7f6e\u4e3a\u5141\u8bb8\u672a\u7b7e\u540d\u7684\u672c\u5730\u811a\u672c\uff1aset-executionpolicy -executionpolicy remotesigned -scope currentuser\n<\/p><\/blockquote>\n<p>A vast majority (if not all) of your C# applications will use void as the return value from Main(), which, as you recall, implicitly returns the error code of zero. To this end, the Main() methods used in this text (beyond the current example) will return void.<br \/>\n\u7edd\u5927\u591a\u6570\uff08\u5982\u679c\u4e0d\u662f\u5168\u90e8\uff09C# \u5e94\u7528\u7a0b\u5e8f\u5c06\u4f7f\u7528 void \u4f5c\u4e3a Main\uff08\uff09 \u7684\u8fd4\u56de\u503c\uff0c\u60a8\u8fd8\u8bb0\u5f97\uff0c\u5b83\u9690\u5f0f\u8fd4\u56de\u9519\u8bef\u4ee3\u7801\u96f6\u3002\u4e3a\u6b64\uff0c\u672c\u6587\u4e2d\u4f7f\u7528\u7684 Main\uff08\uff09 \u65b9\u6cd5\uff08\u5f53\u524d\u793a\u4f8b\u4e4b\u5916\uff09\u5c06\u8fd4\u56de void\u3002<\/p>\n<h2>Processing Command-Line Arguments (Updated 9.0)<\/h2>\n<p>\u5904\u7406\u547d\u4ee4\u884c\u53c2\u6570\uff089.0 \u66f4\u65b0\uff09<\/p>\n<p>Now that you better understand the return value of the Main() method or top-level statements, let\u2019s examine the incoming array of string data. Assume that you now want to update your application to process any possible command-line parameters. One way to do this is using a C# for loop. (Note that C#\u2019s iteration constructs will be examined in some detail near the end of this chapter.)<br \/>\n\u73b0\u5728\u60a8\u5df2\u7ecf\u66f4\u597d\u5730\u4e86\u89e3\u4e86 Main\uff08\uff09 \u65b9\u6cd5\u6216\u9876\u7ea7\u8bed\u53e5\u7684\u8fd4\u56de\u503c\uff0c\u8ba9\u6211\u4eec\u68c0\u67e5\u4e00\u4e0b\u4f20\u5165\u7684\u5b57\u7b26\u4e32\u6570\u636e\u6570\u7ec4\u3002\u5047\u8bbe\u60a8\u73b0\u5728\u60f3\u8981\u66f4\u65b0\u5e94\u7528\u7a0b\u5e8f\u4ee5\u5904\u7406\u4efb\u4f55\u53ef\u80fd\u7684\u547d\u4ee4\u884c\u53c2\u6570\u3002\u6267\u884c\u6b64\u64cd\u4f5c\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528 C# for \u5faa\u73af\u3002\uff08\u8bf7\u6ce8\u610f\uff0c\u5728\u672c\u7ae0\u672b\u5c3e\u5c06\u8be6\u7ec6\u68c0\u67e5 C# \u7684\u8fed\u4ee3\u6784\u9020\uff09\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Display a message and wait for Enter key to be pressed.\n\/\/ \u663e\u793a\u4e00\u6761\u6d88\u606f\u5e76\u7b49\u5f85\u6309\u4e0b Enter \u952e\u3002\nConsole.WriteLine(&quot;***** My First C# App *****&quot;);\nConsole.WriteLine(&quot;Hello World!&quot;);\nConsole.WriteLine();\n\/\/ Process any incoming args.\n\/\/ \u5904\u7406\u4efb\u4f55\u4f20\u5165\u7684\u53c2\u6570\u3002\nfor (int i = 0; i &lt; args.Length; i++)\n{\n    Console.WriteLine(&quot;Arg: {0}&quot;, args&#x5B;i]);\n}\nConsole.ReadLine();\n<\/pre>\n<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/\/ Return an arbitrary error code.\n\/\/ \u8fd4\u56de\u4efb\u610f\u9519\u8bef\u4ee3\u7801\u3002\nreturn 0;\n<\/pre>\n<\/p>\n<blockquote><p>\n\u25a0 Note  this example is using top-level statements, which doesn\u2019t utilize a Main() method. updating the Main() method to accept the args parameter is covered shortly.<br \/>\n\u8bf7\u6ce8\u610f\uff0c\u6b64\u793a\u4f8b\u4f7f\u7528\u7684\u662f\u4e0d\u4f7f\u7528 Main\uff08\uff09 \u65b9\u6cd5\u7684\u9876\u7ea7\u8bed\u53e5\u3002\u66f4\u65b0\u7a0d\u540e\u5c06\u4ecb\u7ecd\u63a5\u53d7 args \u53c2\u6570\u7684 main\uff08\uff09 \u65b9\u6cd5\u3002\n<\/p><\/blockquote>\n<p>Once again, examining the generated IL for the program using top-level statements, notice that the<Main>$ method accepts a string array named args, as shown here (abbreviated for space):<br \/>\n\u518d\u6b21\u4f7f\u7528\u9876\u7ea7\u8bed\u53e5\u68c0\u67e5\u4e3a\u7a0b\u5e8f\u751f\u6210\u7684 IL\uff0c\u8bf7\u6ce8\u610f<Main>$ \u65b9\u6cd5\u63a5\u53d7\u4e00\u4e2a\u540d\u4e3a args \u7684\u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u5982\u4e0b\u6240\u793a\uff08\u7a7a\u683c\u7f29\u5199\uff09\uff1a<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n.class private abstract auto ansi sealed beforefieldinit '&lt;Program&gt;$' extends &#x5B;System.Runtime]System.Object\n{\n    .custom instance void &#x5B;System.Runtime]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()=\n    ( 01 00 00 00 )\n    .method private hidebysig static int32 '&lt;Main&gt;$'(string&#x5B;] args) cil managed\n    {\n        .entrypoint\n    ...\n    } \/\/ end of method '&lt;Program&gt;$'::'&lt;Main&gt;$'\n} \/\/ end of class '&lt;Program&gt;$'\n<\/pre>\n<\/p>\n<p>If the program is still using a Main() method as the entry point, make sure the method signature accepts a string array named args, as follows:<br \/>\n\u5982\u679c\u7a0b\u5e8f\u4ecd\u5728\u4f7f\u7528 Main\uff08\uff09 \u65b9\u6cd5\u4f5c\u4e3a\u5165\u53e3\u70b9\uff0c\u8bf7\u786e\u4fdd\u65b9\u6cd5\u7b7e\u540d\u63a5\u53d7\u540d\u4e3a args \u7684\u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic int Main(string&#x5B;] args)\n{\n...\n}\n<\/pre>\n<\/p>\n<p>Here, you are checking to see whether the array of strings contains some number of items using the Length property of System.Array. As you will see in Chapter 4, all C# arrays actually alias the System.Array class and, therefore, share a common set of members. As you loop over each item in the array, its value is printed to the console window. Supplying the arguments at the command line is equally simple, as shown here:<br \/>\n\u5728\u8fd9\u91cc\uff0c\u60a8\u5c06\u4f7f\u7528 System.Array \u7684 Length \u5c5e\u6027\u68c0\u67e5\u5b57\u7b26\u4e32s \u7684\u6570\u7ec4\u662f\u5426\u5305\u542b\u4e00\u5b9a\u6570\u91cf\u7684\u9879\u3002\u6b63\u5982\u60a8\u5c06\u5728\u7b2c 4 \u7ae0\u4e2d\u770b\u5230\u7684\uff0c\u6240\u6709 C# \u6570\u7ec4\u5b9e\u9645\u4e0a\u90fd\u4e3a\u7cfb\u7edf\u8bbe\u7f6e\u4e86\u522b\u540d\u3002\u6570\u7ec4\u7c7b\uff0c\u56e0\u6b64\u5171\u4eab\u4e00\u7ec4\u516c\u5171\u6210\u5458\u3002\u5faa\u73af\u904d\u5386\u6570\u7ec4\u4e2d\u7684\u6bcf\u4e2a\u9879\u65f6\uff0c\u5176\u503c\u5c06\u6253\u5370\u5230\u63a7\u5236\u53f0\u7a97\u53e3\u3002\u5728\u547d\u4ee4\u884c\u4e2d\u63d0\u4f9b\u53c2\u6570\u540c\u6837\u7b80\u5355\uff0c\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/\/ \u5728\u9879\u76ee\u76ee\u5f55\u8f93\u5165 dotnet run \/arg1 -arg2\nC:\\SimpleCSharpApp&gt;dotnet run \/arg1 -arg2\n\/\/ \u8f93\u51fa\u7ed3\u679c\n***** My First C# App ***** \nHello World!\nArg: \/arg1 \nArg: -arg2\n\n<\/pre>\n<\/p>\n<p>As an alternative to the standard for loop, you may iterate over an incoming string array using the C# foreach keyword. Here is some sample usage (but again, you will see specifics of looping constructs later in this chapter):<br \/>\n\u4f5c\u4e3a\u6807\u51c6 for \u5faa\u73af\u7684\u66ff\u4ee3\u65b9\u6cd5\uff0c\u53ef\u4ee5\u4f7f\u7528 C# foreach \u5173\u952e\u5b57\u5faa\u73af\u8bbf\u95ee\u4f20\u5165\u7684\u5b57\u7b26\u4e32\u6570\u7ec4\u3002\u4e0b\u9762\u662f\u4e00\u4e9b\u793a\u4f8b\u7528\u6cd5\uff08\u4f46\u540c\u6837\uff0c\u60a8\u5c06\u5728\u672c\u7ae0\u540e\u9762\u770b\u5230\u5faa\u73af\u6784\u9020\u7684\u7ec6\u8282\uff09\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Notice you have no need to check the size of the array when using &quot;foreach&quot;.\n\/\/ \u8bf7\u6ce8\u610f\uff0c\u4f7f\u7528 \u201cforeach\u201d \u65f6\u65e0\u9700\u68c0\u67e5\u6570\u7ec4\u7684\u5927\u5c0f\u3002\n\/\/ Process any incoming args using foreach.\n\/\/ \u4f7f\u7528 foreach \u5904\u7406\u4efb\u4f55\u4f20\u5165\u7684\u53c2\u6570\u3002\nforeach (string arg in args)\n{\n    Console.WriteLine(&quot;Arg: {0}&quot;, arg);\n}\nConsole.ReadLine();\nreturn 0;\n<\/pre>\n<\/p>\n<p>Finally, you are also able to access command-line arguments using the static GetCommandLineArgs()method of the System.Environment type. The return value of this method is an array of strings. The first entry holds the name of the application itself, while the remaining elements in the array contain the individual command-line arguments.<br \/>\n\u6700\u540e\uff0c\u60a8\u8fd8\u53ef\u4ee5\u4f7f\u7528\u9759\u6001 GetCommandLineArgs\uff08\uff09 \u8bbf\u95ee\u547d\u4ee4\u884c\u53c2\u6570\u7cfb\u7edf\u73af\u5883\u7c7b\u578b\u7684\u65b9\u6cd5\u3002\u6b64\u65b9\u6cd5\u7684\u8fd4\u56de\u503c\u662f\u5b57\u7b26\u4e32s \u7684\u6570\u7ec4\u3002\u7b2c\u4e00\u4e2a\u6761\u76ee\u4fdd\u5b58\u5e94\u7528\u7a0b\u5e8f\u672c\u8eab\u7684\u540d\u79f0\uff0c\u800c\u6570\u7ec4\u4e2d\u7684\u5176\u4f59\u5143\u7d20\u5305\u542b\u5404\u4e2a\u547d\u4ee4\u884c\u53c2\u6570\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Get arguments using System.Environment.\n\/\/ \u4f7f\u7528 System.Environment \u83b7\u53d6\u53c2\u6570\u3002\nstring&#x5B;] theArgs = Environment.GetCommandLineArgs();\nforeach(string arg in theArgs)\n{\nConsole.WriteLine(&quot;Arg: {0}&quot;, arg);\n}\nConsole.ReadLine();\nreturn 0;\n\n<\/pre>\n<\/p>\n<blockquote><p>\n\u25a0 Note  the GetCommandLineArgs method does not receive the arguments for the application through the Main() method and does not depend on the string[] args parameter.<br \/>\n\u6ce8\u610f GetCommandLineArgs \u65b9\u6cd5\u4e0d\u4f1a\u901a\u8fc7main\uff08\uff09 \u65b9\u6cd5\uff0c\u4e0d\u4f9d\u8d56\u4e8e string[] args \u53c2\u6570\u3002\n<\/p><\/blockquote>\n<p>Of course, it is up to you to determine which command-line arguments your program will respond to (if any) and how they must be formatted (such as with a - or \/ prefix). Here, I simply passed in a series of options that were printed directly to the command prompt. Assume, however, you were creating a newvideo game and programmed your application to process an option named -godmode. If the user starts your application with the flag, you know he is, in fact, a cheater, and you can take an appropriate course of action.<br \/>\n\u5f53\u7136\uff0c\u7531\u60a8\u51b3\u5b9a\u7a0b\u5e8f\u5c06\u54cd\u5e94\u54ea\u4e9b\u547d\u4ee4\u884c\u53c2\u6570\uff08\u5982\u679c\u6709\uff09\u4ee5\u53ca\u5982\u4f55\u683c\u5f0f\u5316\u5b83\u4eec\uff08\u4f8b\u5982\u4f7f\u7528 - \u6216 \/ \u524d\u7f00\uff09\u3002\u5728\u8fd9\u91cc\uff0c\u6211\u53ea\u662f\u4f20\u5165\u4e86\u4e00\u7cfb\u5217\u76f4\u63a5\u6253\u5370\u5230\u547d\u4ee4\u63d0\u793a\u7b26\u7684\u9009\u9879\u3002\u4f46\u662f\uff0c\u5047\u8bbe\u60a8\u6b63\u5728\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u89c6\u9891\u6e38\u620f\uff0c\u5e76\u5bf9\u5e94\u7528\u7a0b\u5e8f\u8fdb\u884c\u4e86\u7f16\u7a0b\uff0c\u4ee5\u5904\u7406\u540d\u4e3a -godmode \u7684\u9009\u9879\u3002\u5982\u679c\u7528\u6237\u4f7f\u7528\u6807\u5fd7\u542f\u52a8\u5e94\u7528\u7a0b\u5e8f\uff0c\u60a8\u5c31\u77e5\u9053\u4ed6\u5b9e\u9645\u4e0a\u662f\u4e00\u4e2a\u4f5c\u5f0a\u8005\uff0c\u60a8\u53ef\u4ee5\u91c7\u53d6\u9002\u5f53\u7684\u64cd\u4f5c\u8fc7\u7a0b\u3002<\/p>\n<h2>Specifying Command-Line Arguments with Visual Studio 2022<\/h2>\n<p>\u4f7f\u7528 Visual Studio 2022 \u6307\u5b9a\u547d\u4ee4\u884c\u53c2\u6570<\/p>\n<p>In the real world, an end user has the option of supplying command-line arguments when starting a program. However, during the development cycle, you might want to specify possible command-line flags for testing purposes. To do so with Visual Studio, right-click the project name in Solution Explorer, select Properties, and then navigate to the Debug tab on the left side. From there, open the new Launch Profile UI, specify the values using the Command Line Arguments text box (see Figure 3-1), and save your changes.<br \/>\n\u5728\u73b0\u5b9e\u4e16\u754c\u4e2d\uff0c\u6700\u7ec8\u7528\u6237\u53ef\u4ee5\u9009\u62e9\u5728\u542f\u52a8\u7a0b\u5e8f\u65f6\u63d0\u4f9b\u547d\u4ee4\u884c\u53c2\u6570\u3002\u4f46\u662f\uff0c\u5728\u5f00\u53d1\u5468\u671f\u4e2d\uff0c\u60a8\u53ef\u80fd\u5e0c\u671b\u6307\u5b9a\u53ef\u80fd\u7684\u547d\u4ee4\u884c\u6807\u5fd7\u4ee5\u8fdb\u884c\u6d4b\u8bd5\u3002\u82e5\u8981\u4f7f\u7528 Visual Studio \u6267\u884c\u6b64\u64cd\u4f5c\uff0c\u8bf7\u5728\u201c\u89e3\u51b3\u65b9\u6848\u8d44\u6e90\u7ba1\u7406\u5668\u201d\u4e2d\u53f3\u952e\u5355\u51fb\u9879\u76ee\u540d\u79f0\uff0c\u9009\u62e9\u201c\u5c5e\u6027\u201d\uff0c\u7136\u540e\u5bfc\u822a\u5230\u5de6\u4fa7\u7684\u201c\u8c03\u8bd5\u201d\u9009\u9879\u5361\u3002\u5728\u6b64\u5904\uff0c\u6253\u5f00\u65b0\u7684\u542f\u52a8\u914d\u7f6e\u6587\u4ef6 UI\uff0c\u4f7f\u7528\u547d\u4ee4\u884c\u53c2\u6570\u6587\u672c\u6846\u6307\u5b9a\u503c\uff08\u8bf7\u53c2\u9605\u56fe 3-1\uff09\uff0c\u7136\u540e\u4fdd\u5b58\u66f4\u6539\u3002<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/miie.net\/img\/pro-csharp10\/images\/0301.png\" alt=\"Alt text\" \/><\/p>\n<p>Figure 3-1. Setting application arguments in Visual Studio<br \/>\n\u56fe 3-1\u3002 \u5728 Visual Studio \u4e2d\u8bbe\u7f6e\u5e94\u7528\u7a0b\u5e8f\u53c2\u6570<\/p>\n<p>After you have established such command-line arguments, they will automatically be passed to the Main() method when debugging or running your application within the Visual Studio IDE.<br \/>\n\u5efa\u7acb\u6b64\u7c7b\u547d\u4ee4\u884c\u53c2\u6570\u540e\uff0c\u5b83\u4eec\u5c06\u81ea\u52a8\u4f20\u9012\u7ed9\u5728 Visual Studio IDE \u4e2d\u8c03\u8bd5\u6216\u8fd0\u884c\u5e94\u7528\u7a0b\u5e8f\u65f6\u7684 Main\uff08\uff09 \u65b9\u6cd5\u3002<\/p>\n<h2>Additional Members of the System.Environment Class (Updated 10.0)<\/h2>\n<p>System.Environment \u7c7b\u7684\u5176\u4ed6\u6210\u5458\uff0810.0 \u66f4\u65b0\uff09<\/p>\n<p>The Environment class exposes a number of extremely helpful methods beyond GetCommandLineArgs(). Specifically, this class allows you to obtain a number of details regarding the operating system currently hosting your .NET 6 application using various static members. To illustrate the usefulness of System.Environment, update your code to call a local method named ShowEnvironmentDetails().<br \/>\n\u73af\u5883\u7c7b\u516c\u5f00\u4e86\u8bb8\u591a\u9664\u4e86 GetCommandLineArgs\uff08\uff09 \u4e4b\u5916\u975e\u5e38\u6709\u7528\u7684\u65b9\u6cd5\u3002\u5177\u4f53\u800c\u8a00\uff0c\u6b64\u7c7b\u5141\u8bb8\u60a8\u4f7f\u7528\u5404\u79cd\u9759\u6001\u6210\u5458\u83b7\u53d6\u6709\u5173\u5f53\u524d\u627f\u8f7d .NET 6 \u5e94\u7528\u7a0b\u5e8f\u7684\u64cd\u4f5c\u7cfb\u7edf\u7684\u8bb8\u591a\u8be6\u7ec6\u4fe1\u606f\u3002\u4e3a\u4e86\u8bf4\u660e\u7cfb\u7edf\u7684\u6709\u7528\u6027\u3002\u73af\u5883\u4e2d\uff0c\u66f4\u65b0\u4ee3\u7801\u4ee5\u8c03\u7528\u540d\u4e3a ShowEnvironmentDetails\uff08\uff09 \u7684\u672c\u5730\u65b9\u6cd5\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Local method within the Top-level statements. \n\/\/ \u9876\u7ea7\u8bed\u53e5\u4e2d\u7684\u672c\u5730\u65b9\u6cd5\u3002 \n\nShowEnvironmentDetails();\n\nConsole.ReadLine(); \nreturn -1;\n\n<\/pre>\n<\/p>\n<p>Implement this method after your top-level statements to call various members of the Environment type:<br \/>\n\u5728\u9876\u7ea7\u8bed\u53e5\u4e4b\u540e\u5b9e\u73b0\u6b64\u65b9\u6cd5\uff0c\u4ee5\u8c03\u7528\u73af\u5883\u7c7b\u578b\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void ShowEnvironmentDetails()\n{\n    \/\/ Print out the drives on this machine,\n    \/\/ \u6253\u5370\u51fa\u6b64\u673a\u5668\u4e0a\u7684\u9a71\u52a8\u5668\n    \/\/ and other interesting details.\n    \/\/ \u4ee5\u53ca\u5176\u4ed6\u6709\u8da3\u7684\u7ec6\u8282\u3002\n    foreach (string drive in Environment.GetLogicalDrives())\n    {\n        Console.WriteLine(&quot;Drive: {0}&quot;, drive);\n    }\n    Console.WriteLine(&quot;OS: {0}&quot;, Environment.OSVersion);\n    Console.WriteLine(&quot;Number of processors: {0}&quot;,Environment.ProcessorCount);\n    Console.WriteLine(&quot;.NET Core Version: {0}&quot;,Environment.Version);\n}\n\n<\/pre>\n<\/p>\n<p>The following output shows a possible test run of invoking this method:<br \/>\n\u4ee5\u4e0b\u8f93\u51fa\u663e\u793a\u4e86\u8c03\u7528\u6b64\u65b9\u6cd5\u7684\u53ef\u80fd\u6d4b\u8bd5\u8fd0\u884c\uff1a<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n***** My First C# App ***** Hello World!\n\nDrive: C:\\\nOS: Microsoft Windows NT 10.0.19042.0 Number of processors: 16\n.NET Core Version: 6.0.0\n<\/pre>\n<\/p>\n<p>The Environment type defines members other than those shown in the previous example. Table 3-1 documents some additional properties of interest; however, be sure to check out the online documentation for full details.<br \/>\n\u73af\u5883\u7c7b\u578b\u5b9a\u4e49\u4e0a\u4e00\u4e2a\u793a\u4f8b\u4e2d\u6240\u793a\u7684\u6210\u5458\u4ee5\u5916\u7684\u6210\u5458\u3002\u8868 3-1 \u8bb0\u5f55\u4e86\u4e00\u4e9b\u611f\u5174\u8da3\u7684\u5176\u4ed6\u5c5e\u6027;\u4f46\u662f\uff0c\u8bf7\u52a1\u5fc5\u67e5\u770b\u5728\u7ebf\u6587\u6863\u4ee5\u83b7\u53d6\u5b8c\u6574\u8be6\u7ec6\u4fe1\u606f\u3002<\/p>\n<p>Table 3-1. Select Properties of System.Environment<\/p>\n<table>\n<tr>\n<th>\nProperty\n<\/th>\n<th>\nMeaning in Life\n<\/th>\n<\/tr>\n<tr>\n<td>\nExitCode<br \/>\n\u9000\u51fa\u4ee3\u7801\n<\/td>\n<td>\nGets or sets the exit code for the application<br \/>\n\u83b7\u53d6\u6216\u8bbe\u7f6e\u5e94\u7528\u7a0b\u5e8f\u7684\u9000\u51fa\u4ee3\u7801\n<\/td>\n<\/tr>\n<tr>\n<td>\nIs64BitOperatingSystem<br \/>\nIs64\u4f4d\u64cd\u4f5c\u7cfb\u7edf\n<\/td>\n<td>\nReturns a bool to represent whether the host machine is running a 64-bit OS<br \/>\n\u8fd4\u56de\u4e00\u4e2a bool \u4ee5\u8868\u793a\u4e3b\u673a\u662f\u5426\u6b63\u5728\u8fd0\u884c 64 \u4f4d\u64cd\u4f5c\u7cfb\u7edf\n<\/td>\n<\/tr>\n<tr>\n<td>\nMachineName<br \/>\n\u8ba1\u7b97\u673a\u540d\u79f0\n<\/td>\n<td>\nGets the name of the current machine<br \/>\n\u83b7\u53d6\u5f53\u524d\u8ba1\u7b97\u673a\u7684\u540d\u79f0\n<\/td>\n<\/tr>\n<tr>\n<td>\nNewLine<br \/>\n\u6362\u884c\u7b26\n<\/td>\n<td>\nGets the newline symbol for the current environment<br \/>\n\u83b7\u53d6\u5f53\u524d\u73af\u5883\u7684\u6362\u884c\u7b26\n<\/td>\n<\/tr>\n<tr>\n<td>\nProcessId (new in 10.0)<br \/>\n\u8fdb\u7a0b ID\uff0810.0 \u7248\uff09\n<\/td>\n<td>\nGets the unique identifier of the current process<br \/>\n\u83b7\u53d6\u5f53\u524d\u8fdb\u7a0b\u7684\u552f\u4e00\u6807\u8bc6\u7b26\n<\/td>\n<\/tr>\n<tr>\n<td>\nProcessPath (new in 10.0)<br \/>\n\u8fdb\u7a0b\u8def\u5f84\uff0810.0 \u7248\uff09\n<\/td>\n<td>\nReturns the path of the executable that started the currently executing process; returns null when the path is not available<br \/>\n\u8fd4\u56de\u542f\u52a8\u5f53\u524d\u6b63\u5728\u6267\u884c\u7684\u8fdb\u7a0b\u7684\u53ef\u6267\u884c\u6587\u4ef6\u7684\u8def\u5f84;\u5f53\u8def\u5f84\u4e0d\u53ef\u7528\u65f6\u8fd4\u56de null\n<\/td>\n<\/tr>\n<tr>\n<td>\nSystemDirectory<br \/>\n\u7cfb\u7edf\u76ee\u5f55\n<\/td>\n<td>\nReturns the full path to the system directory<br \/>\n\u8fd4\u56de\u7cfb\u7edf\u76ee\u5f55\u7684\u5b8c\u6574\u8def\u5f84\n<\/td>\n<\/tr>\n<tr>\n<td>\nUserName<br \/>\n\u7528\u6237\u540d\n<\/td>\n<td>\nReturns the name of the user that started this application<br \/>\n\u8fd4\u56de\u542f\u52a8\u6b64\u5e94\u7528\u7a0b\u5e8f\u7684\u7528\u6237\u7684\u540d\u79f0\n<\/td>\n<\/tr>\n<tr>\n<td>\nVersion\u7248\u672c\n<\/td>\n<td>\nReturns a Version object that represents the version of the .NET Core platform<br \/>\n\u8fd4\u56de\u4e00\u4e2a Version \u5bf9\u8c61\uff0c\u8be5\u5bf9\u8c61\u8868\u793a .NET Core \u5e73\u53f0\u7684\u7248\u672c\n<\/td>\n<\/tr>\n<\/table>\n<h2>Using the System.Console Class<\/h2>\n<p>\u8fd4\u56de\u4e00\u4e2a Version \u5bf9\u8c61\uff0c\u8be5\u5bf9\u8c61\u8868\u793a .NET Core \u5e73\u53f0\u7684\u7248\u672c<\/p>\n<p>Almost all the example applications created over the course of the initial chapters of this book make extensive use of the System.Console class. While it is true that a console user interface (CUI) may not be as enticing as a graphical user interface (GUI) or web application, restricting the early examples to console programs will allow you to keep focused on the syntax of C# and the core aspects of the .NET 6 platform, rather than dealing with the complexities of building desktop GUIs or websites.<br \/>\n\u5728\u672c\u4e66\u7684\u524d\u51e0\u7ae0\u4e2d\u521b\u5efa\u7684\u51e0\u4e4e\u6240\u6709\u793a\u4f8b\u5e94\u7528\u7a0b\u5e8f\u90fd\u5e7f\u6cdb\u4f7f\u7528\u4e86 System.Console \u7c7b\u3002\u867d\u7136\u63a7\u5236\u53f0\u7528\u6237\u754c\u9762 \uff08CUI\uff09 \u786e\u5b9e\u53ef\u80fd\u4e0d\u5982\u56fe\u5f62\u7528\u6237\u754c\u9762 \uff08GUI\uff09 \u6216 Web \u5e94\u7528\u7a0b\u5e8f\u90a3\u4e48\u5438\u5f15\u4eba\uff0c\u4f46\u5c06\u65e9\u671f\u793a\u4f8b\u9650\u5236\u4e3a\u63a7\u5236\u53f0\u7a0b\u5e8f\u5c06\u4f7f\u60a8\u80fd\u591f\u4e13\u6ce8\u4e8e C# \u7684\u8bed\u6cd5\u548c .NET 6 \u5e73\u53f0\u7684\u6838\u5fc3\u65b9\u9762\uff0c\u800c\u4e0d\u662f\u5904\u7406\u6784\u5efa\u684c\u9762 GUI \u6216\u7f51\u7ad9\u7684\u590d\u6742\u6027\u3002<\/p>\n<blockquote><p>\n\u25a0 Note  access to the Console class is now implicitly provided by the global using statements provided by .net 6, negating the need to add in the using System; statement that was required in previous versions of C#\/.net.<br \/>\n\u6ce8\u610f \u5bf9\u63a7\u5236\u53f0\u7c7b\u7684\u8bbf\u95ee\u73b0\u5728\u7531 \u63d0\u4f9b\u7684\u5168\u5c40 using \u8bed\u53e5\u9690\u5f0f\u63d0\u4f9b.net 6\uff0c\u65e0\u9700\u6dfb\u52a0\u4f7f\u7528\u7cfb\u7edf; \u4ee5\u524d\u7248\u672c\u7684 C#\/.net \u4e2d\u9700\u8981\u7684\u8bed\u53e5\u3002\n<\/p><\/blockquote>\n<p>As its name implies, the Console class encapsulates input, output, and error-stream manipulations for console-based applications. Table 3-2 lists some (but definitely not all) members of interest. As you can see, the Console class does provide some members that can spice up a simple command-line application, such as the ability to change background and foreground colors and issue beep noises (in a variety of frequencies!).<br \/>\n\u987e\u540d\u601d\u4e49\uff0cConsole \u7c7b\u5c01\u88c5\u4e86\u57fa\u4e8e\u63a7\u5236\u53f0\u7684\u5e94\u7528\u7a0b\u5e8f\u7684\u8f93\u5165\u3001\u8f93\u51fa\u548c\u9519\u8bef\u6d41\u64cd\u4f5c\u3002\u8868 3-2 \u5217\u51fa\u4e86\u4e00\u4e9b\uff08\u4f46\u7edd\u5bf9\u4e0d\u662f\u5168\u90e8\uff09\u611f\u5174\u8da3\u7684\u6210\u5458\u3002\u5982\u60a8\u6240\u89c1\uff0cConsole \u7c7b\u786e\u5b9e\u63d0\u4f9b\u4e86\u4e00\u4e9b\u53ef\u4ee5\u4e3a\u7b80\u5355\u7684\u547d\u4ee4\u884c\u5e94\u7528\u7a0b\u5e8f\u589e\u6dfb\u8da3\u5473\u7684\u6210\u5458\uff0c\u4f8b\u5982\u66f4\u6539\u80cc\u666f\u548c\u524d\u666f\u8272\u4ee5\u53ca\u53d1\u51fa\u8702\u9e23\u58f0\uff08\u4ee5\u5404\u79cd\u9891\u7387\uff01<\/p>\n<p>Table 3-2. Select Members of System.Console<br \/>\n\u8868 3-2. \u9009\u62e9\u7cfb\u7edf\u63a7\u5236\u53f0\u7684\u6210\u5458<\/p>\n<table>\n<tr>\n<th>\nMember\n<\/th>\n<th>\nMeaning in Life\n<\/th>\n<\/tr>\n<tr>\n<td>\nBeep()\n<\/td>\n<td>\nThis method forces the console to emit a beep of a specified frequency and duration.<br \/>\n\u6b64\u65b9\u6cd5\u5f3a\u5236\u4e3b\u673a\u53d1\u51fa\u6307\u5b9a\u9891\u7387\u548c\u6301\u7eed\u65f6\u95f4\u7684\u8702\u9e23\u58f0\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nBackgroundColor\n<\/td>\n<td>\nThese properties set the background\/foreground colors for the current output.<br \/>\n\u8fd9\u4e9b\u5c5e\u6027\u8bbe\u7f6e\u5f53\u524d\u8f93\u51fa\u7684\u80cc\u666f\u8272\/\u524d\u666f\u8272\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nForegroundColor\n<\/td>\n<td>\nThey may be assigned any member of the ConsoleColor enumeration.<br \/>\n\u53ef\u4ee5\u4e3a\u5b83\u4eec\u5206\u914d\u63a7\u5236\u53f0\u989c\u8272\u679a\u4e3e\u7684\u4efb\u4f55\u6210\u5458\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nBufferHeight<br \/>\nBufferWidth\n<\/td>\n<td>\nThese properties control the height\/width of the console\u2019s buffer area.<br \/>\n\u8fd9\u4e9b\u5c5e\u6027\u63a7\u5236\u63a7\u5236\u53f0\u7f13\u51b2\u533a\u7684\u9ad8\u5ea6\/\u5bbd\u5ea6\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nTitle\n<\/td>\n<td>\nThis property gets or sets the title of the current console.<br \/>\n\u6b64\u5c5e\u6027\u83b7\u53d6\u6216\u8bbe\u7f6e\u5f53\u524d\u63a7\u5236\u53f0\u7684\u6807\u9898\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nWindowHeight<br \/>\nWindowWidth<br \/>\nWindowTop<br \/>\nWindowLeft\n<\/td>\n<td>\nThese properties control the dimensions of the console in relation to the established buffer.<br \/>\n\u8fd9\u4e9b\u5c5e\u6027\u63a7\u5236\u63a7\u5236\u53f0\u76f8\u5bf9\u4e8e\u5df2\u5efa\u7acb\u7f13\u51b2\u533a\u7684\u5c3a\u5bf8\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nClear()\n<\/td>\n<td>\nThis method clears the established buffer and console display area.<br \/>\n\u6b64\u65b9\u6cd5\u6e05\u9664\u5df2\u5efa\u7acb\u7684\u7f13\u51b2\u533a\u548c\u63a7\u5236\u53f0\u663e\u793a\u533a\u57df\u3002\n<\/td>\n<\/tr>\n<\/table>\n<h2>Performing Basic Input and Output (I\/O) with the Console Class<\/h2>\n<p>\u4f7f\u7528\u63a7\u5236\u53f0\u7c7b\u6267\u884c\u57fa\u672c\u8f93\u5165\u548c\u8f93\u51fa \uff08I\/O\uff09<\/p>\n<p>In addition to the members in Table 3-2, the Console type defines a set of methods to capture input and output, all of which are static and are, therefore, called by prefixing the name of the class (Console) to the method name. As you have seen, WriteLine() pumps a text string (including a carriage return) to the output stream. The Write() method pumps text to the output stream without a carriage return. ReadLine() allows you to receive information from the input stream up until the Enter key is pressed, while Read() is used to capture a single character from the input stream. \u9664\u4e86\u8868 3-2 \u4e2d\u7684\u6210\u5458\u4e4b\u5916\uff0c\u63a7\u5236\u53f0\u7c7b\u578b\u8fd8\u5b9a\u4e49\u4e86\u4e00\u7ec4\u7528\u4e8e\u6355\u83b7\u8f93\u5165\u548c\u8f93\u51fa\u7684\u65b9\u6cd5\uff0c\u6240\u6709\u8fd9\u4e9b\u65b9\u6cd5\u90fd\u662f\u9759\u6001\u7684\uff0c\u56e0\u6b64\u901a\u8fc7\u5728\u65b9\u6cd5\u540d\u79f0\u524d\u9762\u52a0\u4e0a\u7c7b\u7684\u540d\u79f0 \uff08Console\uff09 \u6765\u8c03\u7528\u3002\u5982\u60a8\u6240\u89c1\uff0cWriteLine\uff08\uff09 \u5c06\u6587\u672c\u5b57\u7b26\u4e32\uff08\u5305\u62ec\u56de\u8f66\u7b26\uff09\u6cf5\u9001\u5230\u8f93\u51fa\u6d41\u4e2d\u3002Write\uff08\uff09 \u65b9\u6cd5\u5c06\u6587\u672c\u6cf5\u9001\u5230\u8f93\u51fa\u6d41\uff0c\u800c\u4e0d\u5e26\u56de\u8f66\u7b26\u3002ReadLine\uff08\uff09 \u5141\u8bb8\u60a8\u4ece\u8f93\u5165\u6d41\u63a5\u6536\u4fe1\u606f\uff0c\u76f4\u5230\u6309\u4e0b Enter \u952e\uff0c\u800c Read\uff08\uff09 \u7528\u4e8e\u4ece\u8f93\u5165\u6d41\u4e2d\u6355\u83b7\u5355\u4e2a\u5b57\u7b26\u3002<\/p>\n<p>To illustrate simple I\/O using the Console class, create a new Console Application project named BasicConsoleIO and add it to your solution with these CLI commands:<br \/>\n\u82e5\u8981\u8bf4\u660e\u4f7f\u7528\u63a7\u5236\u53f0\u7c7b\u7684\u7b80\u5355 I\/O\uff0c\u8bf7\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a BasicConsoleIO \u7684\u65b0\u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u9879\u76ee\uff0c\u5e76\u4f7f\u7528\u4ee5\u4e0b CLI \u547d\u4ee4\u5c06\u5176\u6dfb\u52a0\u5230\u89e3\u51b3\u65b9\u6848\u4e2d\uff1a<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\"> \n\ndotnet new console -lang c# -n BasicConsoleIO -o .\\BasicConsoleIO -f net6.0 \ndotnet sln .\\Chapter3_AllProjects.sln add .\\BasicConsoleIO\n<\/pre>\n<\/p>\n<p>Replace the Program.cs code with the following:<br \/>\n\u5c06\u7a0b\u5e8f.cs\u4ee3\u7801\u66ff\u6362\u4e3a\u4ee5\u4e0b\u5185\u5bb9\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nConsole.WriteLine(&quot;***** Basic Console I\/O *****&quot;);\nGetUserData();\nConsole.ReadLine();\nstatic void GetUserData()\n{\n}\n\n<\/pre>\n<\/p>\n<blockquote><p>\n\u25a0 Note Visual studio and Visual studio Code both support a number of \u201ccode snippets\u201d that will insert code once activated. the cw code snippet is quite useful during the early chapters of this text, in that it will automatically expand to Console.WriteLine()! to test this for yourself, type in cw somewhere within your code and hit the tab key. note: in Visual studio Code, you hit the tab key once; in Visual studio, you must hit the tab key twice.<br \/>\n\u6ce8\u610f Visual Studio \u548c Visual Studio Code \u90fd\u652f\u6301\u8bb8\u591a\u201c\u4ee3\u7801\u7247\u6bb5\u201d\uff0c\u4e00\u65e6\u6fc0\u6d3b\uff0c\u8fd9\u4e9b\u4ee3\u7801\u7247\u6bb5\u5c31\u4f1a\u63d2\u5165\u4ee3\u7801\u3002CW \u4ee3\u7801\u7247\u6bb5\u5728\u672c\u6587\u7684\u524d\u51e0\u7ae0\u4e2d\u975e\u5e38\u6709\u7528\uff0c\u56e0\u4e3a\u5b83\u5c06\u81ea\u52a8\u5c55\u5f00\u5230 Console.WriteLine\uff08\uff09\uff01\u82e5\u8981\u81ea\u5df1\u5bf9\u6b64\u8fdb\u884c\u6d4b\u8bd5\uff0c\u8bf7\u5728\u4ee3\u7801\u4e2d\u7684\u67d0\u5904\u952e\u5165 CW\uff0c\u7136\u540e\u6309 Tab \u952e\u3002\u6ce8\u610f\uff1a\u5728Visual Studio Code\u4e2d\uff0c\u60a8\u6309\u4e00\u6b21Tab\u952e;\u5728 Visual Studio \u4e2d\uff0c\u5fc5\u987b\u6309\u4e24\u6b21 Tab \u952e\u3002\n<\/p><\/blockquote>\n<p>Implement this method after the top-level statements with logic that prompts the user for some bits of information and echoes each item to the standard output stream. For example, you could ask the user for a name and age (which will be treated as a text value for simplicity, rather than the expected numerical value), as follows: \u5728\u9876\u7ea7\u8bed\u53e5\u4e4b\u540e\u5b9e\u73b0\u6b64\u65b9\u6cd5\uff0c\u5176\u903b\u8f91\u63d0\u793a\u7528\u6237\u8f93\u5165\u4e00\u4e9b\u4fe1\u606f\u4f4d\u5e76\u5c06\u6bcf\u4e2a\u9879\u76ee\u56de\u663e\u5230\u6807\u51c6\u8f93\u51fa\u6d41\u3002\u4f8b\u5982\uff0c\u60a8\u53ef\u4ee5\u8981\u6c42\u7528\u6237\u63d0\u4f9b\u59d3\u540d\u548c\u5e74\u9f84\uff08\u4e3a\u7b80\u5355\u8d77\u89c1\uff0c\u5c06\u88ab\u89c6\u4e3a\u6587\u672c\u503c\uff0c\u800c\u4e0d\u662f\u9884\u671f\u7684\u6570\u503c\uff09\uff0c\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nConsole.WriteLine(&quot;***** Basic Console I\/O *****&quot;);\nGetUserData();\nConsole.ReadLine();\n\nstatic void GetUserData()\n{\n    \/\/ Get name and age.\n    \/\/ \u83b7\u53d6\u59d3\u540d\u548c\u5e74\u9f84\u3002\n    Console.Write(&quot;Please enter your name: &quot;);\n    string userName = Console.ReadLine();\n    Console.Write(&quot;Please enter your age: &quot;);\n    string userAge = Console.ReadLine();\n\n    \/\/ Change echo color, just for fun.\n    \/\/ \u66f4\u6539\u56de\u58f0\u989c\u8272\uff0c\u53ea\u662f\u4e3a\u4e86\u597d\u73a9\u3002\n    ConsoleColor prevColor = Console.ForegroundColor;\n    Console.ForegroundColor = ConsoleColor.Yellow;\n\n    \/\/ Echo to the console.\n    \/\/ \u56de\u663e\u5230\u63a7\u5236\u53f0\u3002\n    Console.WriteLine(&quot;Hello {0}! You are {1} years old.&quot;,userName, userAge);\n\n    \/\/ Restore previous color. \n    \/\/\u6062\u590d\u4ee5\u524d\u7684\u989c\u8272\u3002\n    Console.ForegroundColor = prevColor;\n}\n<\/pre>\n<\/p>\n<p>Not surprisingly, when you run this application, the input data is printed to the console (using a custom color to boot!).<br \/>\n\u6beb\u4e0d\u5947\u602a\uff0c\u5f53\u60a8\u8fd0\u884c\u6b64\u5e94\u7528\u7a0b\u5e8f\u65f6\uff0c\u8f93\u5165\u6570\u636e\u5c06\u6253\u5370\u5230\u63a7\u5236\u53f0\uff08\u4f7f\u7528\u81ea\u5b9a\u4e49\u989c\u8272\u542f\u52a8\uff01<\/p>\n<h2>Formatting Console Output<\/h2>\n<p>\u683c\u5f0f\u5316\u63a7\u5236\u53f0\u8f93\u51fa<\/p>\n<p>During these first few chapters, you might have noticed numerous occurrences of tokens such as {0} and {1} embedded within various string literals. The .NET 6 platform supports a style of string formatting slightly akin to the printf() statement of C. Simply put, when you are defining a string literal that contains segments of data whose value is not known until runtime, you are able to specify a placeholder within the string literal using this curly-bracket syntax. At runtime, the values passed into Console.WriteLine() are substituted for each placeholder.<br \/>\n\u5728\u524d\u51e0\u7ae0\u4e2d\uff0c\u60a8\u53ef\u80fd\u5df2\u7ecf\u6ce8\u610f\u5230\u8bb8\u591a\u6807\u8bb0\u7684\u51fa\u73b0\uff0c\u4f8b\u5982 {0} \u548c{1}\u5d4c\u5165\u5728\u5404\u79cd\u5b57\u7b26\u4e32\u6587\u672c\u4e2d\u3002.NET 6 \u5e73\u53f0\u652f\u6301\u4e00\u79cd\u5b57\u7b26\u4e32\u683c\u5f0f\u6837\u5f0f\uff0c\u7565\u5fae\u7c7b\u4f3c\u4e8e C \u7684 printf\uff08\uff09 \u8bed\u53e5\u3002\u7b80\u800c\u8a00\u4e4b\uff0c\u5f53\u60a8\u5b9a\u4e49\u5305\u542b\u5176\u503c\u5728\u8fd0\u884c\u65f6\u4e4b\u524d\u672a\u77e5\u7684\u6570\u636e\u6bb5\u7684\u5b57\u7b26\u4e32\u6587\u672c\u65f6\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528\u6b64\u5927\u62ec\u53f7\u8bed\u6cd5\u5728\u5b57\u7b26\u4e32\u6587\u672c\u4e2d\u6307\u5b9a\u5360\u4f4d\u7b26\u3002\u5728\u8fd0\u884c\u65f6\uff0c\u4f20\u9012\u7ed9 Console.WriteLine\uff08\uff09 \u7684\u503c\u5c06\u66ff\u6362\u4e3a\u6bcf\u4e2a\u5360\u4f4d\u7b26\u3002<\/p>\n<p>The first parameter to WriteLine() represents a string literal that contains optional placeholders designated by {0}, {1}, {2}, and so forth. Be aware that the first ordinal number of a curly-bracket placeholder always begins with 0. The remaining parameters to WriteLine() are simply the values to be inserted into the respective placeholders.<br \/>\nWriteLine\uff08\uff09 \u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u8868\u793a\u4e00\u4e2a\u5b57\u7b26\u4e32\u6587\u672c\uff0c\u5176\u4e2d\u5305\u542b\u7531 {0}\u3001{1}\u3001{2}\u7b49\u6307\u5b9a\u7684\u53ef\u9009\u5360\u4f4d\u7b26\u3002\u8bf7\u6ce8\u610f\uff0c\u5927\u62ec\u53f7\u5360\u4f4d\u7b26\u7684\u7b2c\u4e00\u4e2a\u5e8f\u53f7\u59cb\u7ec8\u4ee5 0 \u5f00\u5934\u3002WriteLine\uff08\uff09 \u7684\u5176\u4f59\u53c2\u6570\u53ea\u662f\u8981\u63d2\u5165\u5230\u76f8\u5e94\u5360\u4f4d\u7b26\u4e2d\u7684\u503c\u3002<\/p>\n<blockquote><p>\n\u25a0 Note if you have more uniquely numbered curly-bracket placeholders than fill arguments, you will receive a format exception at runtime. however, if you have more fill arguments than placeholders, the unused fill arguments are ignored.<br \/>\n\u6ce8\u610f \u5982\u679c\u552f\u4e00\u7f16\u53f7\u7684\u5927\u62ec\u53f7\u5360\u4f4d\u7b26\u591a\u4e8e\u586b\u5145\u53c2\u6570\uff0c\u5219\u5728\u8fd0\u884c\u65f6\u4f1a\u6536\u5230\u683c\u5f0f\u5f02\u5e38\u3002 \u4f46\u662f\uff0c\u5982\u679c\u586b\u5145\u53c2\u6570\u591a\u4e8e\u5360\u4f4d\u7b26\uff0c\u5219\u5ffd\u7565\u672a\u4f7f\u7528\u7684\u586b\u5145\u53c2\u6570\u3002\n<\/p><\/blockquote>\n<p>It is permissible for a given placeholder to repeat within a given string. For example, if you are a Beatles fan and want to build the string &quot;9, Number 9, Number 9&quot;, you would write this:<br \/>\n\u5141\u8bb8\u7ed9\u5b9a\u5360\u4f4d\u7b26\u5728\u7ed9\u5b9a\u5b57\u7b26\u4e32\u4e2d\u91cd\u590d\u3002\u4f8b\u5982\uff0c\u5982\u679c\u4f60\u662f\u62ab\u5934\u58eb\u4e50\u961f\u7684\u7c89\u4e1d\uff0c\u60f3\u8981\u6784\u5efa\u5b57\u7b26\u4e32\u201c9\uff0c\u6570\u5b579\uff0c\u6570\u5b579\u201d\uff0c\u4f60\u53ef\u4ee5\u8fd9\u6837\u5199\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ John says... \n\/\/ \u7ea6\u7ff0 \u8bf4...\nConsole.WriteLine(&quot;{0}, Number {0}, Number {0}&quot;, 9);\n<\/pre>\n<\/p>\n<p>Also, know that it is possible to position each placeholder in any location within a string literal, and it need not follow an increasing sequence. For example, consider the following code snippet: \u53e6\u5916\uff0c\u8bf7\u6ce8\u610f\uff0c\u53ef\u4ee5\u5c06\u6bcf\u4e2a\u5360\u4f4d\u7b26\u653e\u7f6e\u5728\u5b57\u7b26\u4e32\u6587\u672c\u4e2d\u7684\u4efb\u4f55\u4f4d\u7f6e\uff0c\u5e76\u4e14\u4e0d\u9700\u8981\u9075\u5faa\u9012\u589e\u987a\u5e8f\u3002\u4f8b\u5982\uff0c\u8bf7\u8003\u8651\u4ee5\u4e0b\u4ee3\u7801\u7247\u6bb5\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Prints: 20, 10, 30\n\/\/ \u6253\u5370\uff1a 20\uff0c 10\uff0c 30\nConsole.WriteLine(&quot;{1}, {0}, {2}&quot;, 10, 20, 30);\n<\/pre>\n<\/p>\n<p>Strings can also be formatted using string interpolation, which is covered later in this chapter.<br \/>\n\u8fd8\u53ef\u4ee5\u4f7f\u7528\u5b57\u7b26\u4e32\u5185\u63d2\u6765\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\uff0c\u672c\u7ae0\u7a0d\u540e\u5c06\u5bf9\u6b64\u8fdb\u884c\u4ecb\u7ecd\u3002<\/p>\n<h2>Formatting Numerical Data<\/h2>\n<p>\u683c\u5f0f\u5316\u6570\u503c\u6570\u636e<\/p>\n<p>If you require more elaborate formatting for numerical data, each placeholder can optionally contain various format characters. Table 3-3 shows the most common formatting options.<br \/>\n\u5982\u679c\u9700\u8981\u5bf9\u6570\u503c\u6570\u636e\u8fdb\u884c\u66f4\u7cbe\u7ec6\u7684\u683c\u5f0f\u8bbe\u7f6e\uff0c\u5219\u6bcf\u4e2a\u5360\u4f4d\u7b26\u90fd\u53ef\u4ee5\u9009\u62e9\u5305\u542b\u5404\u79cd\u683c\u5f0f\u5b57\u7b26\u3002\u8868 3-3 \u663e\u793a\u4e86\u6700\u5e38\u89c1\u7684\u683c\u5f0f\u8bbe\u7f6e\u9009\u9879\u3002<\/p>\n<p>Table 3-3. .NET Core Numerical Format Characters<br \/>\n\u8868 3-3. .NET \u6838\u5fc3\u6570\u5b57\u683c\u5f0f\u5b57\u7b26<\/p>\n<table>\n<tr>\n<th>\nString FormatCharacter\n<\/th>\n<th>\nMeaning in Life\n<\/th>\n<\/tr>\n<tr>\n<td>\nC or c\n<\/td>\n<td>\nUsed to format currency. By default, the flag will prefix the local cultural symbol (a dollar sign [$] for US English).<br \/>\n\u7528\u4e8e\u683c\u5f0f\u5316\u8d27\u5e01\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u8be5\u6807\u5fd7\u5c06\u4f5c\u4e3a\u5f53\u5730\u6587\u5316\u7b26\u53f7\u7684\u524d\u7f00\uff08\u7f8e\u5143\u7b26\u53f7 [$] \u8868\u793a\u7f8e\u56fd\u82f1\u8bed\uff09\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nD or d\n<\/td>\n<td>\nUsed to format decimal numbers. This flag may also specify the minimum number of digits used to pad the value.<br \/>\n\u7528\u4e8e\u8bbe\u7f6e\u5341\u8fdb\u5236\u6570\u5b57\u7684\u683c\u5f0f\u3002\u6b64\u6807\u5fd7\u8fd8\u53ef\u4ee5\u6307\u5b9a\u7528\u4e8e\u586b\u5145\u503c\u7684\u6700\u5c0f\u4f4d\u6570\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nE or e\n<\/td>\n<td>\nUsed for exponential notation. Casing controls whether the exponential constant is uppercase (E) or lowercase (e).<br \/>\n\u7528\u4e8e\u6307\u6570\u8868\u793a\u6cd5\u3002\u5927\u5c0f\u5199\u63a7\u5236\u6307\u6570\u5e38\u91cf\u662f\u5927\u5199 \uff08E\uff09 \u8fd8\u662f\u5c0f\u5199 \uff08e\uff09\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nF or f\n<\/td>\n<td>\nUsed for fixed-point formatting. This flag may also specify the minimum number of digits used to pad the value.<br \/>\n\u7528\u4e8e\u5b9a\u70b9\u683c\u5f0f\u3002\u6b64\u6807\u5fd7\u8fd8\u53ef\u4ee5\u6307\u5b9a\u7528\u4e8e\u586b\u5145\u503c\u7684\u6700\u5c0f\u4f4d\u6570\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nG or g\n<\/td>\n<td>\nStands for general. This character can be used to format a number to fixed or exponential format.<br \/>\n\u4ee3\u8868 \u4e00\u822c\u3002\u6b64\u5b57\u7b26\u53ef\u7528\u4e8e\u5c06\u6570\u5b57\u683c\u5f0f\u8bbe\u7f6e\u4e3a\u56fa\u5b9a\u6216\u6307\u6570\u683c\u5f0f\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nN or n\n<\/td>\n<td>\nUsed for basic numerical formatting (with commas).<br \/>\n\u7528\u4e8e\u57fa\u672c\u6570\u5b57\u683c\u5f0f\uff08\u5e26\u9017\u53f7\uff09\u3002\n<\/td>\n<\/tr>\n<tr>\n<td>\nX or x\n<\/td>\n<td>\nUsed for hexadecimal formatting. If you use an uppercase X, your hex format will also contain uppercase characters.<br \/>\n\u7528\u4e8e\u5341\u516d\u8fdb\u5236\u683c\u5f0f\u3002\u5982\u679c\u4f7f\u7528\u5927\u5199 X\uff0c\u5219\u5341\u516d\u8fdb\u5236\u683c\u5f0f\u4e5f\u5c06\u5305\u542b\u5927\u5199\u5b57\u7b26\u3002\n<\/td>\n<\/tr>\n<\/table>\n<p>These format characters are suffixed to a given placeholder value using the colon token (e.g.,{0:C}, {1:d}, {2:X}). To illustrate, update the top-level statements to call a new helper function named FormatNumericalData(). Implement this method in your Program.cs file to format a fixed numerical value in a variety of ways.<br \/>\n\u8fd9\u4e9b\u683c\u5f0f\u5b57\u7b26\u4f7f\u7528\u5192\u53f7\u6807\u8bb0\u540e\u7f00\u4e3a\u7ed9\u5b9a\u7684\u5360\u4f4d\u7b26\u503c\uff08\u4f8b\u5982\uff0c{0\uff1aC} \uff0c {1\uff1ad}\uff0c {2\uff1aX}\uff09.\u4e3a\u4e86\u8bf4\u660e\u8fd9\u4e00\u70b9\uff0c\u8bf7\u66f4\u65b0\u9876\u7ea7\u8bed\u53e5\u4ee5\u8c03\u7528\u540d\u4e3a FormatNumericalData\uff08\uff09 \u7684\u65b0\u5e2e\u52a9\u7a0b\u5e8f\u51fd\u6570\u3002\u5728 Program.cs \u6587\u4ef6\u4e2d\u5b9e\u73b0\u6b64\u65b9\u6cd5\uff0c\u4ee5\u591a\u79cd\u65b9\u5f0f\u683c\u5f0f\u5316\u56fa\u5b9a\u6570\u503c\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nFormatNumericalData();\n\n\/\/ Now make use of some format tags.\n\/\/ \u73b0\u5728\u4f7f\u7528\u4e00\u4e9b\u683c\u5f0f\u6807\u7b7e\u3002\nstatic void FormatNumericalData()\n{\n    Console.WriteLine(&quot;The value 99999 in various formats:&quot;); \n    Console.WriteLine(&quot;c format: {0:c}&quot;, 99999);\n    Console.WriteLine(&quot;d9 format: {0:d9}&quot;, 99999); \n    Console.WriteLine(&quot;f3 format: {0:f3}&quot;, 99999);\n    Console.WriteLine(&quot;n format: {0:n}&quot;, 99999);\n\n    \/\/ Notice that upper- or lowercasing for hex \n    \/\/ \u8bf7\u6ce8\u610f\u5341\u516d\u8fdb\u5236\u7684\u5927\u5199\u6216\u5c0f\u5199\n    \/\/ determines if letters are upper- or lowercase.\n    \/\/ \u786e\u5b9a\u5b57\u6bcd\u662f\u5927\u5199\u8fd8\u662f\u5c0f\u5199\u3002\n    Console.WriteLine(&quot;E format: {0:E}&quot;, 99999); \n    Console.WriteLine(&quot;e format: {0:e}&quot;, 99999); \n    Console.WriteLine(&quot;X format: {0:X}&quot;, 99999); \n    Console.WriteLine(&quot;x format: {0:x}&quot;, 99999);\n}\n<\/pre>\n<\/p>\n<p>The following output shows the result of calling the FormatNumericalData() method:<br \/>\n\u4ee5\u4e0b\u8f93\u51fa\u663e\u793a\u4e86\u8c03\u7528 FormatNumericalData\uff08\uff09 \u65b9\u6cd5\u7684\u7ed3\u679c\uff1a<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nThe value 99999 in various formats:\n\nc format: $99,999.00 d9 format: 000099999\nf3 format: 99999.000\nn format: 99,999.00\nE format: 9.999900E+004\ne format: 9.999900e+004 X format: 1869F\nx format: 1869f\n<\/pre>\n<\/p>\n<p>You will see additional formatting examples where required throughout this text; however, if you are interested in digging into string formatting further, look up the topic \u201cFormatting Types\u201d within the .NET Core documentation.<br \/>\n\u60a8\u5c06\u5728\u672c\u6587\u4e2d\u6839\u636e\u9700\u8981\u770b\u5230\u5176\u4ed6\u683c\u5f0f\u793a\u4f8b;\u4f46\u662f\uff0c\u5982\u679c\u60a8\u6709\u5174\u8da3\u8fdb\u4e00\u6b65\u4e86\u89e3\u5b57\u7b26\u4e32\u683c\u5f0f\u8bbe\u7f6e\uff0c\u8bf7\u5728 .NET Core \u6587\u6863\u4e2d\u67e5\u627e\u4e3b\u9898\u201c\u683c\u5f0f\u8bbe\u7f6e\u7c7b\u578b\u201d\u3002<\/p>\n<h2>Formatting Numerical Data Beyond Console Applications<\/h2>\n<p>\u8bbe\u7f6e\u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u4e4b\u5916\u7684\u6570\u5b57\u6570\u636e\u683c\u5f0f<\/p>\n<p>On a final note, be aware that the use of the string formatting characters is not limited to console programs. This same formatting syntax can be used when calling the static string.Format() method. This can be helpful when you need to compose textual data at runtime for use in any application type (e.g., desktop GUI app, ASP.NET web app, etc.).<br \/>\n\u6700\u540e\uff0c\u8bf7\u6ce8\u610f\uff0c\u5b57\u7b26\u4e32\u683c\u5f0f\u5b57\u7b26\u7684\u4f7f\u7528\u4e0d\u4ec5\u9650\u4e8e\u63a7\u5236\u53f0\u7a0b\u5e8f\u3002\u8c03\u7528\u9759\u6001\u5b57\u7b26\u4e32\u65f6\uff0c\u53ef\u4ee5\u4f7f\u7528\u76f8\u540c\u7684\u683c\u5f0f\u8bed\u6cd5\u3002\u683c\u5f0f\uff08\uff09 \u65b9\u6cd5\u3002\u5f53\u60a8\u9700\u8981\u5728\u8fd0\u884c\u65f6\u64b0\u5199\u6587\u672c\u6570\u636e\u4ee5\u7528\u4e8e\u4efb\u4f55\u5e94\u7528\u7a0b\u5e8f\u7c7b\u578b\uff08\u4f8b\u5982\uff0c\u684c\u9762 GUI \u5e94\u7528\u7a0b\u5e8f\u3001ASP.NET Web \u5e94\u7528\u7a0b\u5e8f\u7b49\uff09\u65f6\uff0c\u8fd9\u4f1a\u5f88\u6709\u5e2e\u52a9\u3002<\/p>\n<p>The string.Format() method returns a new string object, which is formatted according to the provided flags. The following code formats a string in hex:<br \/>\nThe string.Format()\u65b9\u6cd5\u8fd4\u56de\u4e00\u4e2a\u65b0\u7684\u5b57\u7b26\u4e32\u5bf9\u8c61\uff0c\u8be5\u5bf9\u8c61\u6839\u636e\u63d0\u4f9b\u7684\u6807\u5fd7\u8fdb\u884c\u683c\u5f0f\u5316\u3002\u4ee5\u4e0b\u4ee3\u7801\u4ee5\u5341\u516d\u8fdb\u5236\u683c\u5f0f\u8bbe\u7f6e\u5b57\u7b26\u4e32\u7684\u683c\u5f0f\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Using string.Format() to format a string literal. \n\/\/ \u4f7f\u7528string.Format()\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u6587\u672c\u3002\nstring userMessage = string.Format(&quot;100000 in hex is {0:x}&quot;, 100000);\n<\/pre>\n<\/p>\n<h2>Working with System Data Types and Corresponding C# Keywords<\/h2>\n<p>\u4f7f\u7528\u7cfb\u7edf\u6570\u636e\u7c7b\u578b\u548c\u76f8\u5e94\u7684 C# \u5173\u952e\u5b57<\/p>\n<p>Like any programming language, C# defines keywords for fundamental data types, which are used to represent local variables, class data member variables, method return values, and parameters. Unlike other programming languages, however, these keywords are much more than simple compiler-recognized<\/p>\n<p>tokens. Rather, the C# data type keywords are actually shorthand notations for full-blown types in the System namespace. Table 3-4 lists each system data type, its range, the corresponding C# keyword, and the type\u2019s compliance with the Common Language Specification (CLS). All of the system types are in the System namespace, left off the chart for readability. \u4e0e\u4efb\u4f55\u7f16\u7a0b\u8bed\u8a00\u4e00\u6837\uff0cC# \u4e3a\u57fa\u672c\u6570\u636e\u7c7b\u578b\u5b9a\u4e49\u5173\u952e\u5b57\uff0c\u8fd9\u4e9b\u5173\u952e\u5b57\u7528\u4e8e\u8868\u793a\u5c40\u90e8\u53d8\u91cf\u3001\u7c7b\u6570\u636e\u6210\u5458\u53d8\u91cf\u3001\u65b9\u6cd5\u8fd4\u56de\u503c\u548c\u53c2\u6570\u3002\u7136\u800c\uff0c\u4e0e\u5176\u4ed6\u7f16\u7a0b\u8bed\u8a00\u4e0d\u540c\uff0c\u8fd9\u4e9b\u5173\u952e\u5b57\u4e0d\u4ec5\u4ec5\u662f\u7b80\u5355\u7684\u7f16\u8bd1\u5668\u8bc6\u522b\u7684<\/p>\n<p>\u4ee4 \u724c\u3002\u76f8\u53cd\uff0cC# \u6570\u636e\u7c7b\u578b\u5173\u952e\u5b57\u5b9e\u9645\u4e0a\u662f System \u547d\u540d\u7a7a\u95f4\u4e2d\u6210\u719f\u7c7b\u578b\u7684\u7b80\u5199\u8868\u793a\u6cd5\u3002\u8868 3-4 \u5217\u51fa\u4e86\u6bcf\u79cd\u7cfb\u7edf\u6570\u636e\u7c7b\u578b\u3001\u5176\u8303\u56f4\u3001\u76f8\u5e94\u7684 C# \u5173\u952e\u5b57\u4ee5\u53ca\u7c7b\u578b\u662f\u5426\u7b26\u5408\u516c\u5171\u8bed\u8a00\u89c4\u8303 \uff08CLS\uff09\u3002\u6240\u6709\u7cfb\u7edf\u7c7b\u578b\u90fd\u4f4d\u4e8e System \u547d\u540d\u7a7a\u95f4\u4e2d\uff0c\u4e3a\u4e86\u4fbf\u4e8e\u9605\u8bfb\uff0c\u56fe\u8868\u4e2d\u672a\u663e\u793a\u3002<\/p>\n<p>Table 3-4. The Intrinsic Data Types of C#<\/p>\n<table>\n<tr>\n<td>C# Shorthand<\/td>\n<td>CLS Compliant?<\/td>\n<td>System Type<\/td>\n<td>Range<\/td>\n<td>Meaning in Life<\/td>\n<\/tr>\n<tr>\n<td>bool<\/td>\n<td>\u00a0Yes<\/td>\n<td>\u00a0Boolean<\/td>\n<td>\u00a0true or false<\/td>\n<td>\u00a0Represents truth or falsity<br \/>\n        \u4ee3\u8868\u771f\u5047<\/td>\n<\/tr>\n<tr>\n<td>sbyte<\/td>\n<td>\u00a0No<\/td>\n<td>\u00a0SByte<\/td>\n<td>\u00a0\u2013128 to 127<\/td>\n<td>\u00a0Signed 8-bit number<br \/>\n        \u6709\u7b26\u53f7\u7684 8 \u4f4d\u6570\u5b57<\/td>\n<\/tr>\n<tr>\n<td>byte<\/td>\n<td>\u00a0Yes<\/td>\n<td>\u00a0Byte<\/td>\n<td>\u00a00 to 255<\/td>\n<td>\u00a0Unsigned 8-bit number<br \/>\n        \u65e0\u7b26\u53f7 8 \u4f4d\u6570\u5b57<\/td>\n<\/tr>\n<tr>\n<td>short<\/td>\n<td>\u00a0Yes<\/td>\n<td>\u00a0Int16<\/td>\n<td>\u00a0\u201332,768 to 32,767<\/td>\n<td>\u00a0Signed 16-bit number<br \/>\n        \u6709\u7b26\u53f7\u7684 16 \u4f4d\u6570\u5b57<\/td>\n<\/tr>\n<tr>\n<td>ushort<\/td>\n<td>\u00a0No<\/td>\n<td>\u00a0UInt16<\/td>\n<td>\u00a00 to 65,535<\/td>\n<td>\u00a0Unsigned 16-bit number<br \/>\n        \u65e0\u7b26\u53f7 16 \u4f4d\u6570\u5b57<\/td>\n<\/tr>\n<tr>\n<td>int<\/td>\n<td>\u00a0Yes<\/td>\n<td>\u00a0Int32<\/td>\n<td>\u00a0\u20132,147,483,648 to 2,147,483,647<\/td>\n<td>\u00a0Signed 32-bit number<br \/>\n        \u6709\u7b26\u53f7\u7684 32 \u4f4d\u6570\u5b57<\/td>\n<\/tr>\n<tr>\n<td>uint<\/td>\n<td>\u00a0No<\/td>\n<td>\u00a0UInt32<\/td>\n<td>\u00a00 to 4,294,967,295<\/td>\n<td>\u00a0Unsigned 32-bit number<br \/>\n        \u65e0\u7b26\u53f7 32 \u4f4d\u6570\u5b57<\/td>\n<\/tr>\n<tr>\n<td>long<\/td>\n<td>\u00a0Yes<\/td>\n<td>\u00a0Int64<\/td>\n<td>\u00a0\u20139,223,372,036,854,775,808 to 9,223,372,036,854,775,807<\/td>\n<td>Signed 64-bit to number<br \/>\n        \u6709\u7b26\u53f7\u7684 64 \u4f4d\u6570\u5b57<\/td>\n<\/tr>\n<tr>\n<td>ulong<\/td>\n<td>\u00a0No<\/td>\n<td>\u00a0UInt64<\/td>\n<td>\u00a00 to 18,446,744,073,709,551,615<\/td>\n<td>\u00a0Unsigned 64-bit number<br \/>\n        \u65e0\u7b26\u53f7 64 \u4f4d\u6570\u5b57<\/td>\n<\/tr>\n<tr>\n<td>char<\/td>\n<td>\u00a0Yes<\/td>\n<td>\u00a0Char<\/td>\n<td>\u00a0U+0000 to U+ffff<\/td>\n<td>\u00a0Single 16-bit Unicode character<br \/>\n        \u5355\u4e2a 16 \u4f4d Unicode \u5b57\u7b26<\/td>\n<\/tr>\n<tr>\n<td>float<\/td>\n<td>\u00a0Yes<\/td>\n<td>\u00a0Single<\/td>\n<td>\u00a0\u20133.4 1038 to +3.4 1038<\/td>\n<td>\u00a032-bit floating-point number<br \/>\n        32 \u4f4d\u6d6e\u70b9\u6570<\/td>\n<\/tr>\n<tr>\n<td>double<\/td>\n<td>\u00a0Yes<\/td>\n<td>\u00a0Double<\/td>\n<td>\u00a0\u00b15.0 10\u2013324 to \u00b11.7 10308<\/td>\n<td>\u00a064-bit floating-point number<br \/>\n        64 \u4f4d\u6d6e\u70b9\u6570<\/td>\n<\/tr>\n<tr>\n<td>decimal<\/td>\n<td>\u00a0Yes<\/td>\n<td>\u00a0Decimal<\/td>\n<td>\u00a0(\u20137.9 x 1028 to 7.9 x 1028)\/(100 to 28)<\/td>\n<td>\u00a0128-bit signed number<br \/>\n        128 \u4f4d\u6709\u7b26\u53f7\u53f7\u7801<\/td>\n<\/tr>\n<tr>\n<td>string<\/td>\n<td>\u00a0Yes<\/td>\n<td>\u00a0String<\/td>\n<td>\u00a0Limited by system memory<\/td>\n<td>\u00a0Represents a set of Unicode charactersv<\/td>\n<\/tr>\n<tr>\n<td>object<\/td>\n<td>\u00a0Yes<\/td>\n<td>\u00a0Object<\/td>\n<td>\u00a0Can store any data type in an object variable<\/td>\n<td>\u00a0The base class of all types in the .NET universe<br \/>\n        .NET \u9886\u57df\u4e2d\u6240\u6709\u7c7b\u578b\u7684\u57fa\u7c7b<\/td>\n<\/tr>\n<\/table>\n<blockquote><p>\n\u25a0 Note recall from Chapter 1 that CLs-compliant .net Core code can be used by any other .net programming language. if you expose non-CLs-compliant data from your programs, other .net languages might not be able to make use of it.<br \/>\n\u8bf7\u6ce8\u610f\u7b2c 1 \u7ae0\u4e2d\u7684\u56de\u987e\uff0c\u7b26\u5408 CL \u7684 .net Core \u4ee3\u7801\u53ef\u4ee5\u7531\u4efb\u4f55\u5176\u4ed6 .net \u7f16\u7a0b\u8bed\u8a00\u4f7f\u7528\u3002 \u5982\u679c\u4ece\u7a0b\u5e8f\u4e2d\u516c\u5f00\u4e0d\u7b26\u5408 CL \u7684\u6570\u636e\uff0c\u5219\u5176\u4ed6 .NET \u8bed\u8a00\u53ef\u80fd\u65e0\u6cd5\u4f7f\u7528\u5b83\u3002\n<\/p><\/blockquote>\n<h2>Understanding Variable Declaration and Initialization<\/h2>\n<p>\u4e86\u89e3\u53d8\u91cf\u58f0\u660e\u548c\u521d\u59cb\u5316<\/p>\n<p>When you are declaring a local variable (e.g., a variable within a member scope), you do so by specifying the data type, followed by the variable\u2019s name. To begin, create a new Console Application project named BasicDataTypes and add it into the solution using these commands:<br \/>\n\u58f0\u660e\u5c40\u90e8\u53d8\u91cf\uff08\u4f8b\u5982\uff0c\u6210\u5458\u8303\u56f4\u5185\u7684\u53d8\u91cf\uff09\u65f6\uff0c\u53ef\u4ee5\u901a\u8fc7\u6307\u5b9a\u6570\u636e\u7c7b\u578b\uff0c\u540e\u8ddf\u53d8\u91cf\u7684\u540d\u79f0\u6765\u5b9e\u73b0\u3002\u9996\u5148\uff0c\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a BasicDataTypes \u7684\u65b0\u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u9879\u76ee\uff0c\u5e76\u4f7f\u7528\u4ee5\u4e0b\u547d\u4ee4\u5c06\u5176\u6dfb\u52a0\u5230\u89e3\u51b3\u65b9\u6848\u4e2d\uff1a<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ndotnet new console -lang c# -n BasicDataTypes -o .\\BasicDataTypes -f net6.0 \ndotnet sln .\\Chapter3_AllProjects.sln add .\\BasicDataTypes\n<\/pre>\n<\/p>\n<p>Update the code to the following:<br \/>\n\u5c06\u4ee3\u7801\u66f4\u65b0\u4e3a\u4ee5\u4e0b\u5185\u5bb9\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing System.Numerics;\nConsole.WriteLine(&quot;***** Fun with Basic Data Types *****&quot;);\n<\/pre>\n<\/p>\n<p>Now, add the following static local function and call it from the top-level statements:<br \/>\n\u73b0\u5728\uff0c\u6dfb\u52a0\u4ee5\u4e0b\u9759\u6001\u672c\u5730\u51fd\u6570\u5e76\u4ece\u9876\u7ea7\u8bed\u53e5\u8c03\u7528\u5b83\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing System.Numerics;\nConsole.WriteLine(&quot;***** Fun with Basic Data Types *****&quot;);\n\nstatic void LocalVarDeclarations()\n{\n    Console.WriteLine(&quot;=&gt; Data Declarations:&quot;);\n    \/\/ Local variables are declared as so:\n    \/\/ \u5c40\u90e8\u53d8\u91cf\u58f0\u660e\u5982\u4e0b\uff1a\n    \/\/ dataType varName;\n    \/\/ \u6570\u636e\u7c7b\u578b\u53d8\u91cf\u540d\u79f0;\n    int myInt; \n    string myString; Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>Be aware that it is a compiler error to make use of a local variable before assigning an initial value. Given this, it is good practice to assign an initial value to your local data points at the time of declaration. You may do so on a single line or by separating the declaration and assignment into two code statements.<br \/>\n\u8bf7\u6ce8\u610f\uff0c\u5728\u5206\u914d\u521d\u59cb\u503c\u4e4b\u524d\u4f7f\u7528\u5c40\u90e8\u53d8\u91cf\u662f\u7f16\u8bd1\u5668\u9519\u8bef\u3002\u9274\u4e8e\u6b64\uff0c\u6700\u597d\u5728\u58f0\u660e\u65f6\u4e3a\u672c\u5730\u6570\u636e\u70b9\u5206\u914d\u521d\u59cb\u503c\u3002\u53ef\u4ee5\u5728\u4e00\u884c\u4e0a\u6267\u884c\u6b64\u64cd\u4f5c\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7\u5c06\u58f0\u660e\u548c\u8d4b\u503c\u5206\u9694\u4e3a\u4e24\u4e2a\u4ee3\u7801\u8bed\u53e5\u6765\u6267\u884c\u6b64\u64cd\u4f5c\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void LocalVarDeclarations()\n{\n    Console.WriteLine(&quot;=&gt; Data Declarations:&quot;);\n    \/\/ Local variables are declared and initialized as follows: \n    \/\/ \u5c40\u90e8\u53d8\u91cf\u7684\u58f0\u660e\u548c\u521d\u59cb\u5316\u5982\u4e0b\uff1a\n    \/\/ dataType varName = initialValue;\n    \/\/ \u6570\u636e\u7c7b\u578b\u53d8\u91cf\u540d\u79f0;\n    int myInt = 0;\n\n    \/\/ You can also declare and assign on two lines. \n    \/\/  \u60a8\u8fd8\u53ef\u4ee5\u5728\u4e24\u884c\u4e0a\u58f0\u660e\u548c\u8d4b\u503c\u3002\n    string myString;\n    myString = &quot;This is my character data&quot;;\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>It is also permissible to declare multiple variables of the same underlying type on a single line of code, as in the following three bool variables:<br \/>\n\u8fd8\u5141\u8bb8\u5728\u4e00\u884c\u4ee3\u7801\u4e0a\u58f0\u660e\u76f8\u540c\u57fa\u7840\u7c7b\u578b\u7684\u591a\u4e2a\u53d8\u91cf\uff0c\u5982\u4ee5\u4e0b\u4e09\u4e2a\u5e03\u5c14\u53d8\u91cf\u6240\u793a\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void LocalVarDeclarations()\n{\n    Console.WriteLine(&quot;=&gt; Data Declarations:&quot;);\n    int myInt = 0;\n    string myString;\n    myString = &quot;This is my character data&quot;;\n    \/\/ Declare 3 bools on a single line.\n    \/\/ \u5728\u4e00\u884c\u4e0a\u58f0\u660e 3 \u4e2a\u5e03\u5c14\u503c\u3002\n    bool b1 = true, b2 = false, b3 = b1;\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>Since the C# bool keyword is simply a shorthand notation for the System.Boolean structure, it is also possible to allocate any data type using its full name (of course, the same point holds true for any C# data type keyword). Here is the final implementation of LocalVarDeclarations(), which illustrates various ways to declare a local variable:<br \/>\n\u7531\u4e8e C# bool \u5173\u952e\u5b57\u53ea\u662f System.Boolean \u7ed3\u6784\u7684\u7b80\u5199\u8868\u793a\u6cd5\uff0c\u56e0\u6b64\u4e5f\u53ef\u4ee5\u4f7f\u7528\u5176\u5168\u540d\u5206\u914d\u4efb\u4f55\u6570\u636e\u7c7b\u578b\uff08\u5f53\u7136\uff0c\u5bf9\u4e8e\u4efb\u4f55 C# \u6570\u636e\u7c7b\u578b\u5173\u952e\u5b57\u4e5f\u662f\u5982\u6b64\uff09\u3002\u4e0b\u9762\u662f LocalVarDeclarations\uff08\uff09 \u7684\u6700\u7ec8\u5b9e\u73b0\uff0c\u5b83\u8bf4\u660e\u4e86\u58f0\u660e\u5c40\u90e8\u53d8\u91cf\u7684\u5404\u79cd\u65b9\u6cd5\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void LocalVarDeclarations()\n{\n    Console.WriteLine(&quot;=&gt; Data Declarations:&quot;);\n    \/\/ Local variables are declared and initialized as follows:\n    \/\/ \u5c40\u90e8\u53d8\u91cf\u7684\u58f0\u660e\u548c\u521d\u59cb\u5316\u5982\u4e0b\uff1a\n    \/\/ dataType varName = initialValue;\n    \/\/ \u6570\u636e\u7c7b\u578b\u53d8\u91cf\u540d\u79f0 = \u521d\u59cb\u503c;\n    int myInt = 0;\n    string myString;\n    myString = &quot;This is my character data&quot;;\n\n    \/\/ Declare 3 bools on a single line.\n    \/\/\u5728\u4e00\u884c\u4e0a\u58f0\u660e 3 \u4e2a\u5e03\u5c14\u503c\u3002\n    bool b1 = true, b2 = false, b3 = b1;\n\n    \/\/ Use System.Boolean data type to declare a bool.\n    \/\/ \u4f7f\u7528 System.Boolean \u6570\u636e\u7c7b\u578b\u58f0\u660e\u5e03\u5c14\u503c\u3002\n    System.Boolean b4 = false;\n    Console.WriteLine(&quot;Your data: {0}, {1}, {2}, {3}, {4}, {5}&quot;,\n    myInt, myString, b1, b2, b3, b4);\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<h2>The default Literal (New 7.1)<\/h2>\n<p>\u9ed8\u8ba4\u6587\u672c\uff08\u65b0 7.1\uff09<\/p>\n<p>The default literal assigns a variable the default value for its data type. This works for standard data types as well as custom classes (Chapter 5) and generic types (Chapter 10). Create a new method named DefaultDeclarations() and add the following code:<br \/>\n\u9ed8\u8ba4\u6587\u672c\u4e3a\u53d8\u91cf\u5206\u914d\u5176\u6570\u636e\u7c7b\u578b\u7684\u9ed8\u8ba4\u503c\u3002\u8fd9\u9002\u7528\u4e8e\u6807\u51c6\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u81ea\u5b9a\u4e49\u7c7b\uff08\u7b2c 5 \u7ae0\uff09\u548c\u6cdb\u578b\u7c7b\u578b\uff08\u7b2c 10 \u7ae0\uff09\u3002\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a DefaultDeclarations\uff08\uff09 \u7684\u65b0\u65b9\u6cd5\u5e76\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void DefaultDeclarations()\n{\n    Console.WriteLine(&quot;=&gt; Default Declarations:&quot;);\n    int myInt = default;\n    Console.WriteLine(myInt);\n}\n<\/pre>\n<\/p>\n<h2>Using Intrinsic Data Types and the new Operator (Updated 9.0)<\/h2>\n<p>\u4f7f\u7528\u5185\u90e8\u6570\u636e\u7c7b\u578b\u548c\u65b0\u8fd0\u7b97\u7b26\uff089.0 \u66f4\u65b0\uff09<\/p>\n<p>All intrinsic data types support what is known as a default constructor (see Chapter 5). This feature allows you to create a variable using the new keyword, which automatically sets the variable to its default value:<br \/>\n\u6240\u6709\u5185\u90e8\u6570\u636e\u7c7b\u578b\u90fd\u652f\u6301\u6240\u8c13\u7684\u9ed8\u8ba4\u6784\u9020\u51fd\u6570\uff08\u8bf7\u53c2\u9605\u7b2c 5 \u7ae0\uff09\u3002\u6b64\u529f\u80fd\u5141\u8bb8\u60a8\u4f7f\u7528 new \u5173\u952e\u5b57\u521b\u5efa\u53d8\u91cf\uff0c\u8be5\u5173\u952e\u5b57\u4f1a\u81ea\u52a8\u5c06\u53d8\u91cf\u8bbe\u7f6e\u4e3a\u5176\u9ed8\u8ba4\u503c\uff1a<\/p>\n<ul>\n<li>\nbool variables are set to false.<br \/>\n\u5e03\u5c14\u53d8\u91cf\u8bbe\u7f6e\u4e3a false\u3002\n<\/li>\n<li>\nNumeric data is set to 0 (or 0.0 in the case of floating-point data types).<br \/>\n\u6570\u503c\u6570\u636e\u8bbe\u7f6e\u4e3a 0\uff08\u5982\u679c\u662f\u6d6e\u70b9\u6570\u636e\u7c7b\u578b\uff0c\u5219\u8bbe\u7f6e\u4e3a 0.0\uff09\u3002\n<\/li>\n<li>\nchar variables are set to a single empty character.<br \/>\n\u5b57\u7b26\u53d8\u91cf\u8bbe\u7f6e\u4e3a\u5355\u4e2a\u7a7a\u5b57\u7b26\u3002\n<\/li>\n<li>\nBigInteger variables are set to 0.<br \/>\nBigInteger \u53d8\u91cf\u8bbe\u7f6e\u4e3a 0\u3002\n<\/li>\n<li>\nDateTime variables are set to 1\/1\/0001 12:00:00 AM.<br \/>\n\u65e5\u671f\u65f6\u95f4\u53d8\u91cf\u8bbe\u7f6e\u4e3a 1\/1\/0001 12\uff1a00\uff1a00 AM\u3002\n<\/li>\n<li>\nObject references (including strings) are set to null.<br \/>\n\u5bf9\u8c61\u5f15\u7528\uff08\u5305\u62ec\u5b57\u7b26\u4e32s\uff09\u8bbe\u7f6e\u4e3a null\u3002\n<\/li>\n<\/ul>\n<blockquote><p>\n\u25a0 Note  the BigInteger data type mentioned in the previous list will be explained in just a bit.<br \/>\n\u8bf7\u6ce8\u610f\uff0c\u4e0a\u4e00\u4e2a\u5217\u8868\u4e2d\u63d0\u5230\u7684 BigInteger \u6570\u636e\u7c7b\u578b\u5c06\u5728\u7a0d\u4f5c\u8bf4\u660e\u3002\n<\/p><\/blockquote>\n<p>Although it is more cumbersome to use the new keyword when creating a basic data type variable, the following is syntactically well-formed C# code:<br \/>\n\u5c3d\u7ba1\u5728\u521b\u5efa\u57fa\u672c\u6570\u636e\u7c7b\u578b\u53d8\u91cf\u65f6\u4f7f\u7528 new \u5173\u952e\u5b57\u6bd4\u8f83\u9ebb\u70e6\uff0c\u4f46\u4ee5\u4e0b\u662f\u8bed\u6cd5\u683c\u5f0f\u826f\u597d\u7684 C# \u4ee3\u7801\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void NewingDataTypes()\n{\n    Console.WriteLine(&quot;=&gt; Using new to create variables:&quot;);\n    bool b = new bool(); \/\/ Set to false.\n    int i = new int(); \/\/ Set to 0.\n    double d = new double(); \/\/ Set to 0.\n    DateTime dt = new DateTime(); \/\/ Set to 1\/1\/0001 12:00:00 AM\n    Console.WriteLine(&quot;{0}, {1}, {2}, {3}&quot;, b, i, d, dt);\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>C# 9.0 added a shortcut for creating variable instances. This shortcut is simply using the keyword new() without the data type. The updated version of NewingDataTypes is shown here:<br \/>\nC# 9.0 \u6dfb\u52a0\u4e86\u7528\u4e8e\u521b\u5efa\u53d8\u91cf\u5b9e\u4f8b\u7684\u5feb\u6377\u65b9\u5f0f\u3002\u6b64\u5feb\u6377\u65b9\u5f0f\u53ea\u662f\u4f7f\u7528\u5173\u952e\u5b57 new\uff08\uff09\u6ca1\u6709\u6570\u636e\u7c7b\u578b.NewingDataTypes \u7684\u66f4\u65b0\u7248\u672c\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void NewingDataTypesWith9()\n{\n    Console.WriteLine(&quot;=&gt; Using new to create variables:&quot;);\n    bool b = new();             \/\/ Set to false.\n    int i = new();              \/\/ Set to 0.\n    double d = new();           \/\/ Set to 0.\n    DateTime dt = new();        \/\/ Set to 1\/1\/0001 12:00:00 AM\n    Console.WriteLine(&quot;{0}, {1}, {2}, {3}&quot;, b, i, d, dt);\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<h2>Understanding the Data Type Class Hierarchy<\/h2>\n<p>\u4e86\u89e3\u6570\u636e\u7c7b\u578b\u7c7b\u5c42\u6b21\u7ed3\u6784<\/p>\n<p>It is interesting to note that even the primitive .NET data types are arranged in a class hierarchy. If you are new to the world of inheritance, you will discover the full details in Chapter 6. Until then, just understand that types at the top of a class hierarchy provide some default behaviors that are granted to the derived types. The relationship between these core system types can be understood as shown in Figure 3-2.<br \/>\n\u6709\u8da3\u7684\u662f\uff0c\u5373\u4f7f\u662f\u57fa\u5143 .NET \u6570\u636e\u7c7b\u578b\u4e5f\u6392\u5217\u5728\u7c7b\u5c42\u6b21\u7ed3\u6784\u4e2d\u3002\u5982\u679c\u4f60\u662f\u7ee7\u627f\u4e16\u754c\u7684\u65b0\u624b\uff0c\u4f60\u5c06\u5728\u7b2c6\u7ae0\u4e2d\u53d1\u73b0\u5168\u90e8\u7ec6\u8282\u3002\u5728\u6b64\u4e4b\u524d\uff0c\u53ea\u9700\u4e86\u89e3\u7c7b\u5c42\u6b21\u7ed3\u6784\u9876\u90e8\u7684\u7c7b\u578b\u63d0\u4f9b\u4e00\u4e9b\u6388\u4e88\u6d3e\u751f\u7c7b\u578b\u7684\u9ed8\u8ba4\u884c\u4e3a\u3002\u8fd9\u4e9b\u6838\u5fc3\u7cfb\u7edf\u7c7b\u578b\u4e4b\u95f4\u7684\u5173\u7cfb\u53ef\u4ee5\u7406\u89e3\u4e3a\u5982\u56fe3-2\u6240\u793a\u3002<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/miie.net\/img\/pro-csharp10\/images\/0302.png\" alt=\"Alt text\" \/><\/p>\n<p>Figure 3-2. The class hierarchy of system types<br \/>\n\u56fe 3-2\u3002 \u7cfb\u7edf\u7c7b\u578b\u7684\u7c7b\u5c42\u6b21\u7ed3\u6784<\/p>\n<p>Notice that each type ultimately derives from System.Object, which defines a set of methods (e.g., ToString(), Equals(), GetHashCode()) common to all types in the .NET Core base class libraries (these methods are fully detailed in Chapter 6).<br \/>\n\u8bf7\u6ce8\u610f\uff0c\u6bcf\u79cd\u7c7b\u578b\u6700\u7ec8\u90fd\u6d3e\u751f\u81ea System.Object\uff0c\u5b83\u5b9a\u4e49\u4e86\u4e00\u7ec4 .NET Core \u57fa\u7c7b\u5e93\u4e2d\u6240\u6709\u7c7b\u578b\u901a\u7528\u7684\u65b9\u6cd5\uff08\u4f8b\u5982\uff0cToString\uff08\uff09\u3001Equals\uff08\uff09\u3001GetHashCode\uff08\uff09\uff09\uff08\u8fd9\u4e9b\u65b9\u6cd5\u5728\u7b2c 6 \u7ae0\u4e2d\u6709\u8be6\u7ec6\u8bf4\u660e\uff09\u3002<\/p>\n<p>Also note that many numerical data types derive from a class named System.ValueType. Descendants of ValueType are automatically allocated on the stack and, therefore, have a predictable lifetime and are quite efficient. On the other hand, types that do not have System.ValueType in their inheritance chain (such as System.Type, System.String, System.Array, System.Exception, and System.Delegate) are not allocated on the stack but on the garbage-collected heap. (You can find more information on this distinction in Chapter 4.)<br \/>\n\u53e6\u8bf7\u6ce8\u610f\uff0c\u8bb8\u591a\u6570\u503c\u6570\u636e\u7c7b\u578b\u6d3e\u751f\u81ea\u540d\u4e3a System.ValueType \u7684\u7c7b\u3002ValueType \u7684\u540e\u4ee3\u5728\u5806\u6808\u4e0a\u81ea\u52a8\u5206\u914d\uff0c\u56e0\u6b64\u5177\u6709\u53ef\u9884\u6d4b\u7684\u751f\u5b58\u671f\u5e76\u4e14\u975e\u5e38\u9ad8\u6548\u3002\u53e6\u4e00\u65b9\u9762\uff0c\u5728\u5176\u7ee7\u627f\u94fe\u4e2d\u6ca1\u6709 System.ValueType \u7684\u7c7b\u578b\uff08\u5982 System.Type\u3001System.String\u3001System.Array\u3001System.Exception \u548c System.Delegate\uff09\u4e0d\u662f\u5728\u5806\u6808\u4e0a\u5206\u914d\uff0c\u4f46\u5728\u5783\u573e\u6536\u96c6\u5806\u4e0a\u5206\u914d\u3002\uff08\u60a8\u53ef\u4ee5\u5728\u7b2c 4 \u7ae0\u4e2d\u627e\u5230\u6709\u5173\u6b64\u533a\u522b\u7684\u66f4\u591a\u4fe1\u606f\u3002<\/p>\n<p>Without getting too hung up on the details of System.Object and System.ValueType, just understand that because a C# keyword (such as int) is simply shorthand notation for the corresponding system type (in this case, System.Int32), the following is perfectly legal syntax, given that System.Int32 (the C# int) eventually derives from System.Object and, therefore, can invoke any of its public members, as illustrated by this additional helper function:<br \/>\n\u65e0\u9700\u8fc7\u591a\u5173\u6ce8System.Object\u548cSystem.ValueType\u7684\u7ec6\u8282\uff0c\u53ea\u9700\u4e86\u89e3\u56e0\u4e3aC#\u5173\u952e\u5b57\uff08\u5982int\uff09\u53ea\u662f\u76f8\u5e94\u7cfb\u7edf\u7c7b\u578b\uff08\u5728\u672c\u4f8b\u4e2d\u4e3aSystem.Int32\uff09\u7684\u7b80\u5199\u8868\u793a\u6cd5\uff0c\u56e0\u6b64\u4ee5\u4e0b\u662f\u5b8c\u5168\u5408\u6cd5\u7684\u8bed\u6cd5\uff0c\u56e0\u4e3aSystem.Int32\uff08C# int\uff09\u6700\u7ec8\u6d3e\u751f\u81eaSystem.Object \u56e0\u6b64\uff0c\u53ef\u4ee5\u8c03\u7528\u5176\u4efb\u4f55\u516c\u5171\u6210\u5458\uff0c\u5982\u4ee5\u4e0b\u9644\u52a0\u5e2e\u52a9\u7a0b\u5e8f\u51fd\u6570\u6240\u793a\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\nstatic void ObjectFunctionality()\n{\n    Console.WriteLine(&quot;=&gt; System.Object Functionality:&quot;);\n    \/\/ A C# int is really a shorthand for System.Int32,\n    \/\/  C# int \u5b9e\u9645\u4e0a\u662f System.Int32 \u7684\u7b80\u5199\n    \/\/ which inherits the following members from System.Object.\n    \/\/ \u5b83\u4ece System.Object \u7ee7\u627f\u4ee5\u4e0b\u6210\u5458\u3002\n    Console.WriteLine(&quot;12.GetHashCode() = {0}&quot;, 12.GetHashCode());\n    Console.WriteLine(&quot;12.Equals(23) = {0}&quot;, 12.Equals(23));\n    Console.WriteLine(&quot;12.ToString() = {0}&quot;, 12.ToString());\n    Console.WriteLine(&quot;12.GetType() = {0}&quot;, 12.GetType());\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>If you were to call this method from within the top-level statements, you would find the output shown here:<br \/>\n\u5982\u679c\u8981\u4ece\u9876\u7ea7\u8bed\u53e5\u4e2d\u8c03\u7528\u6b64\u65b9\u6cd5\uff0c\u5219\u4f1a\u627e\u5230\u5982\u4e0b\u6240\u793a\u7684\u8f93\u51fa\uff1a<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n=&gt; System.Object Functionality:\n12.GetHashCode() = 12\n12.Equals(23) = False\n12.ToString() = 12\n12.GetType() = System.Int32\n<\/pre>\n<\/p>\n<h2>Understanding the Members of Numerical Data Types<\/h2>\n<p>\u4e86\u89e3\u6570\u503c\u6570\u636e\u7c7b\u578b\u7684\u6210\u5458<\/p>\n<p>To continue experimenting with the intrinsic C# data types, understand that the numerical types of .NET Core support MaxValue and MinValue properties that provide information regarding the range a given type can store. In addition to the MinValue\/MaxValue properties, a given numerical system type may define further useful members. For example, the System.Double type allows you to obtain the values for epsilon and infinity (which might be of interest to those of you with a flair for mathematics). To illustrate, consider the following helper function:<br \/>\n\u82e5\u8981\u7ee7\u7eed\u8bd5\u9a8c\u5185\u90e8 C# \u6570\u636e\u7c7b\u578b\uff0c\u8bf7\u4e86\u89e3 .NET Core \u7684\u6570\u503c\u7c7b\u578b\u652f\u6301 MaxValue \u548c MinValue \u5c5e\u6027\uff0c\u8fd9\u4e9b\u5c5e\u6027\u63d0\u4f9b\u6709\u5173\u7ed9\u5b9a\u7c7b\u578b\u53ef\u4ee5\u5b58\u50a8\u7684\u8303\u56f4\u7684\u4fe1\u606f\u3002\u9664\u4e86 MinValue\/MaxValue \u5c5e\u6027\u4e4b\u5916\uff0c\u7ed9\u5b9a\u7684\u6570\u503c\u7cfb\u7edf\u7c7b\u578b\u8fd8\u53ef\u4ee5\u5b9a\u4e49\u66f4\u591a\u6709\u7528\u7684\u6210\u5458\u3002\u4f8b\u5982\uff0cSystem.Double \u7c7b\u578b\u5141\u8bb8\u60a8\u83b7\u53d6 epsilon \u548c\u65e0\u7a77\u5927\u7684\u503c\uff08\u90a3\u4e9b\u5177\u6709\u6570\u5b66\u5929\u8d4b\u7684\u4eba\u53ef\u80fd\u4f1a\u5bf9\u6b64\u611f\u5174\u8da3\uff09\u3002\u4e3a\u4e86\u8bf4\u660e\u8fd9\u4e00\u70b9\uff0c\u8bf7\u8003\u8651\u4ee5\u4e0b\u5e2e\u52a9\u7a0b\u5e8f\u51fd\u6570\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void DataTypeFunctionality()\n{\n    Console.WriteLine(&quot;=&gt; Data type Functionality:&quot;);\n    Console.WriteLine(&quot;Max of int: {0}&quot;, int.MaxValue);\n    Console.WriteLine(&quot;Min of int: {0}&quot;, int.MinValue);\n    Console.WriteLine(&quot;Max of double: {0}&quot;, double.MaxValue);\n    Console.WriteLine(&quot;Min of double: {0}&quot;, double.MinValue);\n    Console.WriteLine(&quot;double.Epsilon: {0}&quot;, double.Epsilon);\n    Console.WriteLine(&quot;double.PositiveInfinity: {0}&quot;,\n    double.PositiveInfinity);\n    Console.WriteLine(&quot;double.NegativeInfinity: {0}&quot;,\n    double.NegativeInfinity);\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>When you define a literal whole number (such as 500), the runtime will default the data type to an int. Likewise, literal floating-point data (such as 55.333) will default to a double. To set the underlying data type to a long, use suffix l or L (4L). To declare a float variable, use the suffix f or F to the raw numerical value (5.3F), and use the suffix m or M to a floating-point number to declare a decimal (300.5M). This becomes more important when declaring variables implicitly, which is covered later in this chapter.<br \/>\n\u5b9a\u4e49\u6587\u672c\u6574\u6570\uff08\u5982 500\uff09\u65f6\uff0c\u8fd0\u884c\u65f6\u4f1a\u5c06\u6570\u636e\u7c7b\u578b\u9ed8\u8ba4\u4e3a int\u3002\u540c\u6837\uff0c\u6587\u672c\u6d6e\u70b9\u6570\u636e\uff08\u5982 55.333\uff09\u5c06\u9ed8\u8ba4\u4e3a\u53cc\u7cbe\u5ea6\u3002\u82e5\u8981\u5c06\u57fa\u7840\u6570\u636e\u7c7b\u578b\u8bbe\u7f6e\u4e3a\u957f\u6574\u578b\uff0c\u8bf7\u4f7f\u7528\u540e\u7f00 l \u6216 L \uff084L\uff09\u3002\u82e5\u8981\u58f0\u660e\u6d6e\u70b9\u53d8\u91cf\uff0c\u8bf7\u4f7f\u7528\u540e\u7f00 f \u6216 F \u5230\u539f\u59cb\u6570\u503c \uff085.3F\uff09\uff0c\u5e76\u4f7f\u7528\u540e\u7f00 m \u6216 M \u5230\u6d6e\u70b9\u6570\u6765\u58f0\u660e\u5341\u8fdb\u5236 \uff08300.5M\uff09\u3002\u5728\u9690\u5f0f\u58f0\u660e\u53d8\u91cf\u65f6\uff0c\u8fd9\u4e00\u70b9\u53d8\u5f97\u66f4\u52a0\u91cd\u8981\uff0c\u672c\u7ae0\u7a0d\u540e\u5c06\u5bf9\u6b64\u8fdb\u884c\u4ecb\u7ecd\u3002<\/p>\n<h2>Understanding the Members of System.Boolean<\/h2>\n<p>\u4e86\u89e3\u7cfb\u7edf\u5e03\u5c14\u503c\u7684\u6210\u5458<\/p>\n<p>Next, consider the System.Boolean data type. The only valid assignment a C# bool can take is from the set {true || false}. Given this point, it should be clear that System.Boolean does not support a MinValue\/MaxValue property set but rather TrueString\/FalseString (which yields the string &quot;True&quot; or &quot;False&quot;, respectively). Here is an example:<br \/>\n\u63a5\u4e0b\u6765\uff0c\u8003\u8651 System.Boolean \u6570\u636e\u7c7b\u578b\u3002C# bool \u53ef\u4ee5\u63a5\u53d7\u7684\u552f\u4e00\u6709\u6548\u8d4b\u503c\u662f\u4ece\u96c6\u5408 {true || false} \u4e2d\u83b7\u53d6\u7684\u3002\u9274\u4e8e\u8fd9\u4e00\u70b9\uff0c\u5e94\u8be5\u5f88\u6e05\u695aSystem.Boolean\u4e0d\u652f\u6301\u8bbe\u7f6e\u4e86 MinValue\/MaxValue \u5c5e\u6027\uff0c\u4f46\u8bbe\u7f6e\u4e86 TrueString\/FalseString\uff08\u751f\u6210\u5b57\u7b26\u4e32\u201cTrue\u201d\u6216\u5206\u522b\u662f\u201c\u5047\u201d\uff09\u3002\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nConsole.WriteLine(&quot;bool.FalseString: {0}&quot;, bool.FalseString);\n\nConsole.WriteLine(&quot;bool.TrueString: {0}&quot;, bool.TrueString);\n<\/pre>\n<\/p>\n<h2>Understanding the Members of System.Char<\/h2>\n<p>\u4e86\u89e3 System.Char \u7684\u6210\u5458<\/p>\n<p>C# textual data is represented by the string and char keywords, which are simple shorthand notations for System.String and System.Char, both of which are Unicode under the hood. As you might already know, a string represents a contiguous set of characters (e.g., &quot;Hello&quot;), while the char can represent a single slot in a string (e.g., 'H').<br \/>\nC# \u6587\u672c\u6570\u636e\u7531\u5b57\u7b26\u4e32\u548c char \u5173\u952e\u5b57\u8868\u793a\uff0c\u5b83\u4eec\u662f System.String \u548c System.Char \u7684\u7b80\u5355\u901f\u8bb0\u7b26\u53f7\uff0c\u4e24\u8005\u90fd\u662f Unicode \u5e95\u5c42\u3002\u60a8\u53ef\u80fd\u5df2\u7ecf\u77e5\u9053\uff0c\u5b57\u7b26\u4e32\u8868\u793a\u4e00\u7ec4\u8fde\u7eed\u7684\u5b57\u7b26\uff08\u4f8b\u5982\uff0c\u201cHello\u201d\uff09\uff0c\u800c\u5b57\u7b26\u53ef\u4ee5\u8868\u793a\u5b57\u7b26\u4e32\u4e2d\u7684\u5355\u4e2a\u63d2\u69fd\uff08\u4f8b\u5982\uff0c\u201cH\u201d\uff09\u3002<\/p>\n<p>The System.Char type provides you with a great deal of functionality beyond the ability to hold a single point of character data. Using the static methods of System.Char, you are able to determine whether a given character is numerical, alphabetical, a point of punctuation, or whatnot. Consider the following method:<br \/>\nSystem.Char \u7c7b\u578b\u4e3a\u60a8\u63d0\u4f9b\u4e86\u5927\u91cf\u529f\u80fd\uff0c\u8d85\u51fa\u4e86\u4fdd\u5b58\u5355\u70b9\u5b57\u7b26\u6570\u636e\u7684\u80fd\u529b\u3002\u4f7f\u7528 System.Char \u7684\u9759\u6001\u65b9\u6cd5\uff0c\u60a8\u53ef\u4ee5\u786e\u5b9a\u7ed9\u5b9a\u5b57\u7b26\u662f\u6570\u5b57\u3001\u5b57\u6bcd\u3001\u6807\u70b9\u7b26\u53f7\u8fd8\u662f\u5176\u4ed6\u5b57\u7b26\u3002\u8bf7\u8003\u8651\u4ee5\u4e0b\u65b9\u6cd5\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\nstatic void CharFunctionality()\n{\n    Console.WriteLine(&quot;=&gt; char type Functionality:&quot;);\n    char myChar = 'a';\n    Console.WriteLine(&quot;char.IsDigit('a'): {0}&quot;, char.IsDigit(myChar));\n    Console.WriteLine(&quot;char.IsLetter('a'): {0}&quot;, char.IsLetter(myChar));\n    Console.WriteLine(&quot;char.IsWhiteSpace('Hello There', 5): {0}&quot;,char.IsWhiteSpace(&quot;Hello There&quot;, 5));\n    Console.WriteLine(&quot;char.IsWhiteSpace('Hello There', 6): {0}&quot;,char.IsWhiteSpace(&quot;Hello There&quot;, 6));\n    Console.WriteLine(&quot;char.IsPunctuation('?'): {0}&quot;, char.IsPunctuation('?'));\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>As illustrated in the previous method, many members of System.Char have two calling conventions: a single character or a string with a numerical index that specifies the position of the character to test.<br \/>\n\u5982\u524d\u9762\u7684\u65b9\u6cd5\u6240\u793a\uff0cSystem.Char \u7684\u8bb8\u591a\u6210\u5458\u5177\u6709\u4e24\u79cd\u8c03\u7528\u7ea6\u5b9a\uff1a\u5355\u4e2a\u5b57\u7b26\u6216\u5177\u6709\u6307\u5b9a\u8981\u6d4b\u8bd5\u7684\u5b57\u7b26\u4f4d\u7f6e\u7684\u6570\u5b57\u7d22\u5f15\u7684\u5b57\u7b26\u4e32\u3002<\/p>\n<h2>Parsing Values from String Data<\/h2>\n<p>\u4ece\u5b57\u7b26\u4e32\u6570\u636e\u89e3\u6790\u503c<\/p>\n<p>The .NET data types provide the ability to generate a variable of their underlying type given a textual equivalent (e.g., parsing). This technique can be extremely helpful when you want to convert some user input data (such as a selection from a GUI-based, drop-down list box) into a numerical value. Consider the following parsing logic within a method named ParseFromStrings():<br \/>\n.NET \u6570\u636e\u7c7b\u578b\u63d0\u4f9b\u4e86\u5728\u7ed9\u5b9a\u6587\u672c\u7b49\u6548\u9879\uff08\u4f8b\u5982\uff0c\u5206\u6790\uff09\u7684\u60c5\u51b5\u4e0b\u751f\u6210\u5176\u57fa\u7840\u7c7b\u578b\u7684\u53d8\u91cf\u7684\u529f\u80fd\u3002\u5f53\u60a8\u60f3\u8981\u5c06\u67d0\u4e9b\u7528\u6237\u8f93\u5165\u6570\u636e\uff08\u4f8b\u5982\u4ece\u57fa\u4e8e GUI \u7684\u4e0b\u62c9\u5217\u8868\u6846\u4e2d\u9009\u62e9\u7684\u5185\u5bb9\uff09\u8f6c\u6362\u4e3a\u6570\u503c\u65f6\uff0c\u6b64\u6280\u672f\u975e\u5e38\u6709\u7528\u3002\u5728\u540d\u4e3a ParseFromStrings\uff08\uff09 \u7684\u65b9\u6cd5\u4e2d\u8003\u8651\u4ee5\u4e0b\u89e3\u6790\u903b\u8f91\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\nstatic void ParseFromStrings()\n{\n    Console.WriteLine(&quot;=&gt; Data type parsing:&quot;);\n    bool b = bool.Parse(&quot;True&quot;);\n    Console.WriteLine(&quot;Value of b: {0}&quot;, b);\n    double d = double.Parse(&quot;99.884&quot;);\n    Console.WriteLine(&quot;Value of d: {0}&quot;, d);\n    int i = int.Parse(&quot;8&quot;);\n    Console.WriteLine(&quot;Value of i: {0}&quot;, i);\n    char c = Char.Parse(&quot;w&quot;);\n    Console.WriteLine(&quot;Value of c: {0}&quot;, c);\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<h2>Using TryParse to Parse Values from String Data<\/h2>\n<p>\u4f7f\u7528 TryParse \u4ece\u5b57\u7b26\u4e32\u6570\u636e\u4e2d\u89e3\u6790\u503c<\/p>\n<p>One issue with the preceding code is that an exception will be thrown if the string cannot be cleanly converted to the correct data type. For example, the following will fail at runtime:<br \/>\n\u4e0a\u8ff0\u4ee3\u7801\u7684\u4e00\u4e2a\u95ee\u9898\u662f\uff0c\u5982\u679c\u5b57\u7b26\u4e32\u65e0\u6cd5\u5b8c\u5168\u8f6c\u6362\u4e3a\u6b63\u786e\u7684\u6570\u636e\u7c7b\u578b\uff0c\u5219\u4f1a\u5f15\u53d1\u5f02\u5e38\u3002\u4f8b\u5982\uff0c\u4ee5\u4e0b\u5185\u5bb9\u5c06\u5728\u8fd0\u884c\u65f6\u5931\u8d25\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nbool b = bool.Parse(&quot;Hello&quot;);\n<\/pre>\n<\/p>\n<p>One solution is to wrap each call to Parse() in a try-catch block (exception handling is covered in detail in Chapter 7), which can add a lot of code, or use a TryParse() statement. The TryParse() statement takes an out parameter (the out modifier is covered in detail in Chapter 4) and returns a bool if the parsing was successful. Create a new method named ParseFromStringWithTryParse() and add the following code:<br \/>\n\u4e00\u79cd\u89e3\u51b3\u65b9\u6848\u662f\u5bf9 Parse\uff08\uff09 \u7684\u6bcf\u4e2a\u8c03\u7528\u5305\u88c5\u5728\u4e00\u4e2a try-catch \u5757\u4e2d\uff08\u7b2c 7 \u7ae0\u8be6\u7ec6\u4ecb\u7ecd\u4e86\u5f02\u5e38\u5904\u7406\uff09\uff0c\u8fd9\u53ef\u4ee5\u6dfb\u52a0\u5927\u91cf\u4ee3\u7801\uff0c\u6216\u4f7f\u7528 TryParse\uff08\uff09 \u8bed\u53e5\u3002 TryParse\uff08\uff09 \u8bed\u53e5\u91c7\u7528\u4e00\u4e2a out \u53c2\u6570\uff08\u7b2c 4 \u7ae0\u8be6\u7ec6\u4ecb\u7ecd\u4e86 out \u4fee\u9970\u7b26\uff09\uff0c\u5982\u679c\u89e3\u6790\u6210\u529f\uff0c\u5219\u8fd4\u56de\u4e00\u4e2a\u5e03\u5c14\u503c\u3002\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a ParseFromStringWithTryParse\uff08\uff09 \u7684\u65b0\u65b9\u6cd5\uff0c\u5e76\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\nstatic void ParseFromStringsWithTryParse()\n{\n    Console.WriteLine(&quot;=&gt; Data type parsing with TryParse:&quot;);\n    if (bool.TryParse(&quot;True&quot;, out bool b))\n    {\n        Console.WriteLine(&quot;Value of b: {0}&quot;, b);\n    }\n    else\n    {\n        Console.WriteLine(&quot;Default value of b: {0}&quot;, b);\n    }\n    string value = &quot;Hello&quot;;\n    if (double.TryParse(value, out double d))\n    {\n        Console.WriteLine(&quot;Value of d: {0}&quot;, d);\n    }\n    else\n    {\n        Console.WriteLine(&quot;Failed to convert the input ({0}) to a double and the variable was assigned the default {1}&quot;, value, d);\n    }\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>If you are new to programming and do not know how if\/else statements work, they are covered later in this chapter in detail. The important item to note from the preceding example is that if a string can be converted to the requested data type, the TryParse() method returns true and assigns the parsed value to the variable passed into the method. If the value cannot be parsed, the variable is assigned its default value, and the TryParse() method returns false.<br \/>\n\u5982\u679c\u60a8\u4e0d\u719f\u6089\u7f16\u7a0b\u5e76\u4e14\u4e0d\u77e5\u9053 if\/else \u8bed\u53e5\u7684\u5de5\u4f5c\u539f\u7406\uff0c\u672c\u7ae0\u7a0d\u540e\u5c06\u8be6\u7ec6\u4ecb\u7ecd\u5b83\u4eec\u3002\u524d\u9762\u793a\u4f8b\u4e2d\u9700\u8981\u6ce8\u610f\u7684\u91cd\u8981\u4e8b\u9879\u662f\uff0c\u5982\u679c\u5b57\u7b26\u4e32\u53ef\u4ee5\u8f6c\u6362\u4e3a\u8bf7\u6c42\u7684\u6570\u636e\u7c7b\u578b\uff0c\u5219 TryParse\uff08\uff09 \u65b9\u6cd5\u8fd4\u56de true \u5e76\u5c06\u89e3\u6790\u7684\u503c\u5206\u914d\u7ed9\u4f20\u9012\u7ed9\u8be5\u65b9\u6cd5\u7684\u53d8\u91cf\u3002\u5982\u679c\u65e0\u6cd5\u89e3\u6790\u8be5\u503c\uff0c\u5219\u4e3a\u53d8\u91cf\u5206\u914d\u5176\u9ed8\u8ba4\u503c\uff0c\u5e76\u4e14 TryParse\uff08\uff09 \u65b9\u6cd5\u8fd4\u56de false\u3002<\/p>\n<h2>Using System.DateTime and System.TimeSpan (Updated 10.0)<\/h2>\n<p>\u4f7f\u7528 System.DateTime \u548c System.TimeSpan\uff08\u66f4\u65b0\u7684 10.0\uff09<\/p>\n<p>The System namespace defines a few useful data types for which there are no C# keywords, such as the DateTime and TimeSpan structures.<br \/>\nSystem \u547d\u540d\u7a7a\u95f4\u5b9a\u4e49\u4e86\u4e00\u4e9b\u6ca1\u6709 C# \u5173\u952e\u5b57\u7684\u6709\u7528\u6570\u636e\u7c7b\u578b\uff0c\u4f8b\u5982\u65e5\u671f\u65f6\u95f4\u548c\u65f6\u95f4\u8de8\u5ea6\u7ed3\u6784\u3002<\/p>\n<p>The DateTime type contains data that represents a specific date (month, day, year) and time value, both of which may be formatted in a variety of ways using the supplied members. The TimeSpan structure allows you to easily define and transform units of time using various members.<br \/>\nDateTime \u7c7b\u578b\u5305\u542b\u8868\u793a\u7279\u5b9a\u65e5\u671f\uff08\u6708\u3001\u65e5\u3001\u5e74\uff09\u548c\u65f6\u95f4\u503c\u7684\u6570\u636e\uff0c\u8fd9\u4e24\u8005\u90fd\u53ef\u4ee5\u4f7f\u7528\u63d0\u4f9b\u7684\u6210\u5458\u4ee5\u591a\u79cd\u65b9\u5f0f\u8bbe\u7f6e\u683c\u5f0f\u3002TimeSpan \u7ed3\u6784\u5141\u8bb8\u60a8\u4f7f\u7528\u5404\u79cd\u6210\u5458\u8f7b\u677e\u5b9a\u4e49\u548c\u8f6c\u6362\u65f6\u95f4\u5355\u4f4d\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\nstatic void UseDatesAndTimes()\n{\n    Console.WriteLine(&quot;=&gt; Dates and Times:&quot;);\n    \/\/ This constructor takes (year, month, day).\n    \/\/ \u6b64\u6784\u9020\u51fd\u6570\u9700\u8981\uff08\u5e74\u3001\u6708\u3001\u65e5\uff09\u3002\n    DateTime dt = new DateTime(2015, 10, 17);\n\n    \/\/ What day of the month is this?\n    \/\/ \u8fd9\u662f\u6bcf\u6708\u7684\u54ea\u4e00\u5929\uff1f\n    Console.WriteLine(&quot;The day of {0} is {1}&quot;, dt.Date, dt.DayOfWeek);\n\n    \/\/ Month is now December.\n    \/\/ \u6708\u4efd\u73b0\u5728\u662f 12 \u6708\u3002\n    dt = dt.AddMonths(2);\n    Console.WriteLine(&quot;Daylight savings: {0}&quot;, dt.IsDaylightSavingTime());\n\n    \/\/ This constructor takes (hours, minutes, seconds).\n    \/\/ \u6b64\u6784\u9020\u51fd\u6570\u9700\u8981\uff08\u5c0f\u65f6\u3001\u5206\u949f\u3001\u79d2\uff09\u3002\n    TimeSpan ts = new TimeSpan(4, 30, 0);\n    Console.WriteLine(ts);\n\n    \/\/ Subtract 15 minutes from the current TimeSpan and\n    \/\/ \u4ece\u5f53\u524d\u65f6\u95f4\u8de8\u5ea6\u4e2d\u51cf\u53bb 15 \u5206\u949f\uff0c\u7136\u540e\n    \/\/ print the result.\n    \/\/ \u6253\u5370\u7ed3\u679c\u3002\n    Console.WriteLine(ts.Subtract(new TimeSpan(0, 15, 0)));\n}\n<\/pre>\n<\/p>\n<p>The DateOnly and TimeOnly structs were added in .NET 6\/C# 10, and each represents half of the DateTime type. The DateOnly struct aligns with the SQL Server Date type, and the TimeOnly struct aligns with the SQL Server Time type. The following code shows the new types in action:<br \/>\nDateOnly \u548c TimeOnly \u7ed3\u6784\u662f\u5728 .NET 6\/C# 10 \u4e2d\u6dfb\u52a0\u7684\uff0c\u6bcf\u4e2a\u7ed3\u6784\u90fd\u8868\u793a DateTime \u7c7b\u578b\u7684\u4e00\u534a\u3002DateOnly \u7ed3\u6784\u4e0e SQL Server Date \u7c7b\u578b\u5bf9\u9f50\uff0cTimeOnly \u7ed3\u6784\u4e0e SQL Server Time \u7c7b\u578b\u5bf9\u9f50\u3002\u4ee5\u4e0b\u4ee3\u7801\u663e\u793a\u4e86\u64cd\u4f5c\u4e2d\u7684\u65b0\u7c7b\u578b\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void UseDatesAndTimes()\n{\n    Console.WriteLine(&quot;=&gt; Dates and Times:&quot;);\n    ...\n    DateOnly d = new DateOnly(2021, 07, 21);\n    Console.WriteLine(d);\n    TimeOnly t = new TimeOnly(13, 30, 0, 0);\n    Console.WriteLine(t);\n}\n<\/pre>\n<\/p>\n<h2>Working with the System.Numerics Namespace<\/h2>\n<p>\u4f7f\u7528 System.Numerics \u547d\u540d\u7a7a\u95f4<\/p>\n<p>The System.Numerics namespace defines a structure named BigInteger. As its name implies, the BigInteger data type can be used when you need to represent humongous numerical values, which are not constrained by a fixed upper or lower limit.<br \/>\n\u547d\u540d\u7a7a\u95f4\u5b9a\u4e49\u4e86\u4e00\u4e2a\u540d\u4e3a BigInteger \u7684\u7ed3\u6784\u3002\u987e\u540d\u601d\u4e49\uff0c\u5f53\u60a8\u9700\u8981\u8868\u793a\u4e0d\u53d7\u56fa\u5b9a\u4e0a\u9650\u6216\u4e0b\u9650\u7ea6\u675f\u7684\u5e9e\u5927\u6570\u503c\u65f6\uff0c\u53ef\u4ee5\u4f7f\u7528 BigInteger \u6570\u636e\u7c7b\u578b\u3002<\/p>\n<blockquote><p>\n\u25a0 Note the System.Numerics namespace defines a second structure named Complex, which allows you to model mathematically complex numerical data (e.g., imaginary units, real data, hyperbolic tangents). Consult the .net Core documentation if you are interested.<br \/>\n\u8bf7\u6ce8\u610f\uff0cSystem.Numerics \u547d\u540d\u7a7a\u95f4\u5b9a\u4e49\u4e86\u540d\u4e3a Complex \u7684\u7b2c\u4e8c\u4e2a\u7ed3\u6784\uff0c\u5b83\u5141\u8bb8\u60a8\u5bf9\u6570\u5b66\u4e0a\u590d\u6742\u7684\u6570\u503c\u6570\u636e\uff08\u4f8b\u5982\uff0c\u865a\u6570\u5355\u4f4d\u3001\u5b9e\u6570\u6570\u636e\u3001\u53cc\u66f2\u6b63\u5207\u7ebf\uff09\u8fdb\u884c\u5efa\u6a21\u3002\u5982\u679c\u60a8\u6709\u5174\u8da3\uff0c\u8bf7\u53c2\u9605 .net Core \u6587\u6863\u3002\n<\/p><\/blockquote>\n<p>While many of your .NET Core applications might never need to make use of the BigInteger structure, if you do find the need to define a massive numerical value, your first step is to add the following using directive to the file:<br \/>\n\u867d\u7136\u8bb8\u591a .NET Core \u5e94\u7528\u7a0b\u5e8f\u53ef\u80fd\u6c38\u8fdc\u4e0d\u9700\u8981\u4f7f\u7528 BigInteger \u7ed3\u6784\uff0c\u4f46\u5982\u679c\u60a8\u53d1\u73b0\u9700\u8981\u5b9a\u4e49\u5927\u91cf\u6570\u503c\uff0c\u5219\u7b2c\u4e00\u6b65\u662f\u5c06\u4ee5\u4e0b using \u6307\u4ee4\u6dfb\u52a0\u5230\u6587\u4ef6\u4e2d\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ BigInteger lives here! BigInteger\u4f4f\u5728\u8fd9\u91cc\uff01\nusing System.Numerics;\n<\/pre>\n<\/p>\n<p>At this point, you can create a BigInteger variable using the new operator. Within the constructor, you can specify a numerical value, including floating-point data. However, C# implicitly types non-floating-point numbers as an int and floating-point numbers as a double. How, then, can you set BigInteger to a massive value while not overflowing the default data types used for raw numerical values?<br \/>\n\u6b64\u65f6\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528 new \u8fd0\u7b97\u7b26\u521b\u5efa BigInteger \u53d8\u91cf\u3002\u5728\u6784\u9020\u51fd\u6570\u4e2d\uff0c\u53ef\u4ee5\u6307\u5b9a\u6570\u503c\uff0c\u5305\u62ec\u6d6e\u70b9\u6570\u636e\u3002\u4f46\u662f\uff0cC# \u5c06\u975e\u6d6e\u70b9\u6570\u9690\u5f0f\u952e\u5165\u4e3a int\uff0c\u5c06\u6d6e\u70b9\u6570\u952e\u5165\u4e3a\u53cc\u7cbe\u5ea6\u6570\u3002\u90a3\u4e48\uff0c\u5982\u4f55\u5c06 BigInteger \u8bbe\u7f6e\u4e3a\u5927\u91cf\u503c\uff0c\u540c\u65f6\u4e0d\u6ea2\u51fa\u7528\u4e8e\u539f\u59cb\u6570\u503c\u7684\u9ed8\u8ba4\u6570\u636e\u7c7b\u578b\uff1f<\/p>\n<p>The simplest approach is to establish the massive numerical value as a text literal, which can be converted into a BigInteger variable via the static Parse() method. If required, you can also pass in a byte array directly to the constructor of the BigInteger class.<br \/>\n\u6700\u7b80\u5355\u7684\u65b9\u6cd5\u662f\u5c06\u5927\u91cf\u6570\u503c\u5efa\u7acb\u4e3a\u6587\u672c\u6587\u5b57\uff0c\u53ef\u4ee5\u901a\u8fc7\u9759\u6001 Parse\uff08\uff09 \u65b9\u6cd5\u5c06\u5176\u8f6c\u6362\u4e3a BigInteger \u53d8\u91cf\u3002\u5982\u679c\u9700\u8981\uff0c\u8fd8\u53ef\u4ee5\u5c06\u5b57\u8282\u6570\u7ec4\u76f4\u63a5\u4f20\u9012\u7ed9 BigInteger \u7c7b\u7684\u6784\u9020\u51fd\u6570\u3002<\/p>\n<blockquote><p>\n\u25a0 Note after you assign a value to a BigInteger variable, you cannot change it, as the data is immutable. however, the BigInteger class defines a number of members that will return new BigInteger objects based on your data modifications (such as the static Multiply() method used in the following code sample).<br \/>\n\u6ce8\u610f \u5c06\u503c\u5206\u914d\u7ed9 BigInteger \u53d8\u91cf\u540e\uff0c\u65e0\u6cd5\u66f4\u6539\u5b83\uff0c\u56e0\u4e3a\u6570\u636e\u662f\u4e0d\u53ef\u53d8\u7684\u3002\u4f46\u662f\uff0cBigInteger \u7c7b\u5b9a\u4e49\u4e86\u8bb8\u591a\u6210\u5458\uff0c\u8fd9\u4e9b\u6210\u5458\u5c06\u6839\u636e\u60a8\u7684\u6570\u636e\u4fee\u6539\uff08\u5982\u4ee5\u4e0b\u4ee3\u7801\u793a\u4f8b\u4e2d\u4f7f\u7528\u7684\u9759\u6001 Multiply\uff08\uff09 \u65b9\u6cd5\uff09\u8fd4\u56de\u65b0\u7684 BigInteger \u5bf9\u8c61\u3002\n<\/p><\/blockquote>\n<p>In any case, after you have defined a BigInteger variable, you will find this class defines similar members as other intrinsic C# data types (e.g., float, int). In addition, the BigInteger class defines several static members that allow you to apply basic mathematical expressions (such as adding and multiplying) to BigInteger variables. Here is an example of working with the BigInteger class:<br \/>\n\u5728\u4efb\u4f55\u60c5\u51b5\u4e0b\uff0c\u5728\u5b9a\u4e49 BigInteger \u53d8\u91cf\u540e\uff0c\u60a8\u4f1a\u53d1\u73b0\u6b64\u7c7b\u5b9a\u4e49\u7684\u6210\u5458\u4e0e\u5176\u4ed6\u5185\u90e8 C# \u6570\u636e\u7c7b\u578b\uff08\u4f8b\u5982\uff0cfloat\u3001int\uff09\u7c7b\u4f3c\u3002\u6b64\u5916\uff0cBigInteger \u7c7b\u5b9a\u4e49\u4e86\u51e0\u4e2a\u9759\u6001\u6210\u5458\uff0c\u8fd9\u4e9b\u6210\u5458\u5141\u8bb8\u60a8\u5c06\u57fa\u672c\u6570\u5b66\u8868\u8fbe\u5f0f\uff08\u5982\u52a0\u6cd5\u548c\u4e58\u6cd5\uff09\u5e94\u7528\u4e8e BigInteger \u53d8\u91cf\u3002\u4e0b\u9762\u662f\u4f7f\u7528 BigInteger \u7c7b\u7684\u793a\u4f8b\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing System.Numerics;\n\nstatic void UseBigInteger()\n{\n    Console.WriteLine(&quot;=&gt; Use BigInteger:&quot;);\n    BigInteger biggy =\n    BigInteger.Parse(&quot;9999999999999999999999999999999999999999999999&quot;);\n    Console.WriteLine(&quot;Value of biggy is {0}&quot;, biggy);\n    Console.WriteLine(&quot;Is biggy an even value?: {0}&quot;, biggy.IsEven);\n    Console.WriteLine(&quot;Is biggy a power of two?: {0}&quot;, biggy.IsPowerOfTwo);\n    BigInteger reallyBig = BigInteger.Multiply(biggy,\n    BigInteger.Parse(&quot;8888888888888888888888888888888888888888888&quot;));\n    Console.WriteLine(&quot;Value of reallyBig is {0}&quot;, reallyBig);\n}\n<\/pre>\n<\/p>\n<p>It is also important to note that the BigInteger data type responds to C#\u2019s intrinsic mathematical operators, such as +, -, and <em>. Therefore, rather than calling BigInteger.Multiply() to multiply two huge numbers, you could author the following code:<br \/>\n\u540c\u6837\u91cd\u8981\u7684\u662f\u8981\u6ce8\u610f\uff0cBigInteger \u6570\u636e\u7c7b\u578b\u54cd\u5e94 C# \u7684\u5185\u90e8\u6570\u5b66\u8fd0\u7b97\u7b26\uff0c\u5982 +\u3001- \u548c <\/em>\u3002\u56e0\u6b64\uff0c\u4e0e\u5176\u8c03\u7528 BigInteger.Multiply\uff08\uff09 \u6765\u4e58\u4ee5\u4e24\u4e2a\u5927\u6570\u5b57\uff0c\u4e0d\u5982\u7f16\u5199\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \nBigInteger reallyBig2 = biggy * reallyBig;\n<\/pre>\n<\/p>\n<p>At this point, I hope you understand that the C# keywords representing basic data types have a corresponding type in the .NET Core base class libraries, each of which exposes a fixed functionality. While I have not detailed each member of these data types, you are in a great position to dig into the details as you see fit. Be sure to consult the .NET Core documentation for full details regarding the various .NET data types\u2014you will likely be surprised at the amount of built-in functionality.<br \/>\n\u6b64\u65f6\uff0c\u6211\u5e0c\u671b\u60a8\u4e86\u89e3\u8868\u793a\u57fa\u672c\u6570\u636e\u7c7b\u578b\u7684 C# \u5173\u952e\u5b57\u5728 .NET Core \u57fa\u7c7b\u5e93\u4e2d\u5177\u6709\u76f8\u5e94\u7684\u7c7b\u578b\uff0c\u6bcf\u4e2a\u57fa\u7c7b\u5e93\u90fd\u516c\u5f00\u4e00\u4e2a\u56fa\u5b9a\u7684\u529f\u80fd\u3002\u867d\u7136\u6211\u6ca1\u6709\u8be6\u7ec6\u8bf4\u660e\u8fd9\u4e9b\u6570\u636e\u7c7b\u578b\u7684\u6bcf\u4e2a\u6210\u5458\uff0c\u4f46\u60a8\u53ef\u4ee5\u6839\u636e\u9700\u8981\u6df1\u5165\u4e86\u89e3\u8be6\u7ec6\u4fe1\u606f\u3002\u8bf7\u52a1\u5fc5\u67e5\u9605 .NET Core \u6587\u6863\uff0c\u4e86\u89e3\u6709\u5173\u5404\u79cd .NET \u6570\u636e\u7c7b\u578b\u7684\u5b8c\u6574\u8be6\u7ec6\u4fe1\u606f - \u60a8\u53ef\u80fd\u4f1a\u5bf9\u5185\u7f6e\u529f\u80fd\u7684\u6570\u91cf\u611f\u5230\u60ca\u8bb6\u3002<\/p>\n<h2>Using Digit Separators (New 7.0)<\/h2>\n<p>\u4f7f\u7528\u6570\u5b57\u5206\u9694\u7b26\uff08\u65b0\u7248 7.0\uff09<\/p>\n<p>Sometimes when assigning large numbers to a numeric variable, there are more digits than the eye can keep track of. C# 7.0 introduced the underscore (<em>) as a digit separator (for integer, long, decimal, double data, or hex types). C# 7.2 allows for hex values (and the new binary literal, covered next, to start with an underscore, after the opening declaration). Here is an example of using the new digit separator:<br \/>\n\u6709\u65f6\uff0c\u5f53\u4e3a\u6570\u503c\u53d8\u91cf\u5206\u914d\u5927\u6570\u5b57\u65f6\uff0c\u6570\u5b57\u591a\u4e8e\u8089\u773c\u53ef\u4ee5\u8ddf\u8e2a\u7684\u6570\u5b57\u3002C# 7.0 \u5f15\u5165\u4e86\u4e0b\u5212\u7ebf \uff08<\/em>\uff09 \u4f5c\u4e3a\u6570\u5b57\u5206\u9694\u7b26\uff08\u7528\u4e8e\u6574\u6570\u3001\u957f\u6574\u578b\u3001\u5341\u8fdb\u5236\u3001\u53cc\u7cbe\u5ea6\u6570\u636e\u6216\u5341\u516d\u8fdb\u5236\u7c7b\u578b\uff09\u3002C# 7.2 \u5141\u8bb8\u5341\u516d\u8fdb\u5236\u503c\uff08\u4ee5\u53ca\u4e0b\u9762\u4ecb\u7ecd\u7684\u65b0\u4e8c\u8fdb\u5236\u6587\u672c\uff0c\u5728\u5f00\u59cb\u58f0\u660e\u4e4b\u540e\u4ee5\u4e0b\u5212\u7ebf\u5f00\u5934\uff09\u3002\u4e0b\u9762\u662f\u4f7f\u7528\u65b0\u6570\u5b57\u5206\u9694\u7b26\u7684\u793a\u4f8b\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void DigitSeparators()\n{\n    Console.WriteLine(&quot;=&gt; Use Digit Separators:&quot;);\n    Console.Write(&quot;Integer:&quot;);\n    Console.WriteLine(123_456);\n    Console.Write(&quot;Long:&quot;);\n    Console.WriteLine(123_456_789L);\n    Console.Write(&quot;Float:&quot;);\n    Console.WriteLine(123_456.1234F);\n    Console.Write(&quot;Double:&quot;);\n    Console.WriteLine(123_456.12);\n    Console.Write(&quot;Decimal:&quot;);\n    Console.WriteLine(123_456.12M);\n    \/\/Updated in 7.2, Hex can begin with _\n    Console.Write(&quot;Hex:&quot;);\n    Console.WriteLine(0x_00_00_FF);\n}\n<\/pre>\n<\/p>\n<h2>Using Binary Literals (New 7.0\/7.2)<\/h2>\n<p>\u4f7f\u7528\u4e8c\u8fdb\u5236\u6587\u672c\uff08\u65b0\u7248 7.0\/7.2\uff09<\/p>\n<p>C# 7.0 introduces a new literal for binary values, for example, for creating bit masks. The new digit separator works with binary literals, and C# 7.2 allows for binary and hex numbers to start with an underscore. Now, binary numbers can be written as you would expect. Here is an example:<br \/>\nC# 7.0 \u4e3a\u4e8c\u8fdb\u5236\u503c\u5f15\u5165\u4e86\u65b0\u7684\u6587\u672c\uff0c\u4f8b\u5982\uff0c\u7528\u4e8e\u521b\u5efa\u4f4d\u63a9\u7801\u3002\u65b0\u7684\u6570\u5b57\u5206\u9694\u7b26\u9002\u7528\u4e8e\u4e8c\u8fdb\u5236\u6587\u672c\uff0cC# 7.2 \u5141\u8bb8\u4e8c\u8fdb\u5236\u548c\u5341\u516d\u8fdb\u5236\u6570\u5b57\u4ee5\u4e0b\u5212\u7ebf\u5f00\u5934\u3002\u73b0\u5728\uff0c\u4e8c\u8fdb\u5236\u6570\u53ef\u4ee5\u6309\u60a8\u7684\u671f\u671b\u7f16\u5199\u3002\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\uff1a<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n0b_0001_0000\n<\/pre>\n<\/p>\n<p>Here is a method that shows using the new literals with the digit separator:<br \/>\n\u4e0b\u9762\u662f\u4e00\u4e2a\u663e\u793a\u4f7f\u7528\u5e26\u6709\u6570\u5b57\u5206\u9694\u7b26\u7684\u65b0\u6587\u672c\u7684\u65b9\u6cd5\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \nstatic void BinaryLiterals()\n{\n    \/\/Updated in 7.2, Binary can begin with _\n    Console.WriteLine(&quot;=&gt; Use Binary Literals:&quot;);\n    Console.WriteLine(&quot;Sixteen: {0}&quot;, 0b_0001_0000);\n    Console.WriteLine(&quot;Thirty Two: {0}&quot;, 0b_0010_0000);\n    Console.WriteLine(&quot;Sixty Four: {0}&quot;, 0b_0100_0000);\n}\n<\/pre>\n<\/p>\n<h2>Working with String Data<\/h2>\n<p>\u4f7f\u7528\u5b57\u7b26\u4e32\u6570\u636e<\/p>\n<p>System.String provides a number of methods you would expect from such a utility class, including methods that return the length of the character data, find substrings within the current string, and convert to and from uppercase\/lowercase. Table 3-5 lists some (but by no means all) of the interesting members.<br \/>\nSystem.String \u63d0\u4f9b\u4e86\u8bb8\u591a\u671f\u671b\u4ece\u6b64\u7c7b\u5b9e\u7528\u7a0b\u5e8f\u7c7b\u83b7\u5f97\u7684\u65b9\u6cd5\uff0c\u5305\u62ec\u8fd4\u56de\u5b57\u7b26\u6570\u636e\u957f\u5ea6\u3001\u67e5\u627e\u5f53\u524d\u5b57\u7b26\u4e32\u4e2d\u7684\u5b50\u5b57\u7b26\u4e32\u4ee5\u53ca\u4e0e\u5927\u5199\/\u5c0f\u5199\u76f8\u4e92\u8f6c\u6362\u7684\u65b9\u6cd5\u3002\u8868 3-5 \u5217\u51fa\u4e86\u4e00\u4e9b\uff08\u4f46\u7edd\u4e0d\u662f\u5168\u90e8\uff09\u6709\u8da3\u7684\u6210\u5458\u3002<br \/>\nTable 3-5. Select Members of System.String<br \/>\n\u8868 3-5. \u9009\u62e9\u7cfb\u7edf\u5b57\u7b26\u4e32\u7684\u6210\u5458<\/p>\n<table>\n<tr>\n<td>String Member<\/td>\n<td>Meaning in Life<\/td>\n<\/tr>\n<tr>\n<td>Length<\/td>\n<td>This property returns the length of the current string.<br \/>\n        \u6b64\u5c5e\u6027\u8fd4\u56de\u5f53\u524d\u5b57\u7b26\u4e32\u7684\u957f\u5ea6\u3002<\/td>\n<\/tr>\n<tr>\n<td>Compare()<\/td>\n<td>This static method compares two strings.<br \/>\n        \u6b64\u9759\u6001\u65b9\u6cd5\u6bd4\u8f83\u4e24\u4e2a\u5b57\u7b26\u4e32\u3002<\/td>\n<\/tr>\n<tr>\n<td>Contains()<\/td>\n<td>This method determines whether a string contains a specific substring.<br \/>\n        \u6b64\u65b9\u6cd5\u786e\u5b9a\u5b57\u7b26\u4e32\u662f\u5426\u5305\u542b\u7279\u5b9a\u7684\u5b50\u5b57\u7b26\u4e32\u3002<\/td>\n<\/tr>\n<tr>\n<td>Equals()<\/td>\n<td>This method tests whether two string objects contain identical character data.<br \/>\n        \u6b64\u65b9\u6cd5\u6d4b\u8bd5\u4e24\u4e2a\u5b57\u7b26\u4e32\u5bf9\u8c61\u662f\u5426\u5305\u542b\u76f8\u540c\u7684\u5b57\u7b26\u6570\u636e\u3002<\/td>\n<\/tr>\n<tr>\n<td>Format()<\/td>\n<td>This static method formats a string using other primitives (e.g., numerical data, other strings) and the {0} notation examined earlier in this chapter.<br \/>\n        \u6b64\u9759\u6001\u65b9\u6cd5\u4f7f\u7528\u5176\u4ed6\u57fa\u5143\uff08\u4f8b\u5982\uff0c\u6570\u503c\u6570\u636e\u3001\u5176\u4ed6\u5b57\u7b26\u4e32\uff09\u548c\u672c\u7ae0\u524d\u9762\u7814\u7a76\u7684{0}\u8868\u793a\u6cd5\u6765\u683c\u5f0f\u5316\u5b57\u7b26\u4e32\u3002<\/td>\n<\/tr>\n<tr>\n<td>Insert()<\/td>\n<td>This method inserts a string within a given string.<br \/>\n        \u6b64\u65b9\u6cd5\u5728\u7ed9\u5b9a\u5b57\u7b26\u4e32\u4e2d\u63d2\u5165\u5b57\u7b26\u4e32\u3002<\/td>\n<\/tr>\n<tr>\n<td>PadLeft() \\ PadRight()<\/td>\n<td>These methods are used to pad a string with some characters.<br \/>\n        \u8fd9\u4e9b\u65b9\u6cd5\u7528\u4e8e\u7528\u4e00\u4e9b\u5b57\u7b26\u586b\u5145\u5b57\u7b26\u4e32\u3002<\/td>\n<\/tr>\n<tr>\n<td>Remove() \\ Replace()<\/td>\n<td>These methods are used to receive a copy of a string with modifications (characters removed or replaced).<br \/>\n        \u8fd9\u4e9b\u65b9\u6cd5\u7528\u4e8e\u63a5\u6536\u7ecf\u8fc7\u4fee\u6539\uff08\u5220\u9664\u6216\u66ff\u6362\u5b57\u7b26\uff09\u7684\u5b57\u7b26\u4e32\u526f\u672c\u3002<\/td>\n<\/tr>\n<tr>\n<td>Split()<\/td>\n<td>This method returns a String array containing the substrings in this instance that are delimited by elements of a specified char array or string array.<br \/>\n        \u6b64\u65b9\u6cd5\u8fd4\u56de\u4e00\u4e2a String \u6570\u7ec4\uff0c\u5176\u4e2d\u5305\u542b\u6b64\u5b9e\u4f8b\u4e2d\u7531\u6307\u5b9a char \u6570\u7ec4\u6216\u5b57\u7b26\u4e32\u6570\u7ec4\u7684\u5143\u7d20\u5206\u9694\u7684\u5b50\u5b57\u7b26\u4e32\u3002\n        <\/td>\n<\/tr>\n<tr>\n<td>Trim()<\/td>\n<td>This method removes all occurrences of a set of specified characters from the beginning and end of the current string.<br \/>\n         \u6b64\u65b9\u6cd5\u4ece\u5f53\u524d\u5b57\u7b26\u4e32\u7684\u5f00\u5934\u548c\u7ed3\u5c3e\u5220\u9664\u4e00\u7ec4\u6307\u5b9a\u5b57\u7b26\u7684\u6240\u6709\u5339\u914d\u9879\u3002<\/td>\n<\/tr>\n<tr>\n<td>ToUpper() \\ ToLower()<\/td>\n<td>These methods create a copy of the current string in uppercase or lowercase format, respectively.<br \/>\n        \u8fd9\u4e9b\u65b9\u6cd5\u5206\u522b\u4ee5\u5927\u5199\u6216\u5c0f\u5199\u683c\u5f0f\u521b\u5efa\u5f53\u524d\u5b57\u7b26\u4e32\u7684\u526f\u672c\u3002<\/td>\n<\/tr>\n<\/table>\n<h2>Performing Basic String Manipulation<\/h2>\n<p>\u6267\u884c\u57fa\u672c\u5b57\u7b26\u4e32\u64cd\u4f5c<\/p>\n<p>Working with the members of System.String is as you would expect. Simply declare a string variable and make use of the provided functionality via the dot operator. Be aware that a few of the members of System. String are static members and are, therefore, called at the class (rather than the object) level.<br \/>\n\u4e0e System.String \u7684\u6210\u5458\u4e00\u8d77\u5de5\u4f5c\u662f\u60a8\u6240\u671f\u671b\u7684\u3002\u53ea\u9700\u58f0\u660e\u4e00\u4e2a\u5b57\u7b26\u4e32\u53d8\u91cf\uff0c\u5e76\u901a\u8fc7\u70b9\u8fd0\u7b97\u7b26\u4f7f\u7528\u63d0\u4f9b\u7684\u529f\u80fd\u3002\u8bf7\u6ce8\u610f\uff0c\u7cfb\u7edf\u7684\u4e00\u4e9b\u6210\u5458\u3002\u5b57\u7b26\u4e32\u662f\u9759\u6001\u6210\u5458\uff0c\u56e0\u6b64\u5728\u7c7b\uff08\u800c\u4e0d\u662f\u5bf9\u8c61\uff09\u7ea7\u522b\u8c03\u7528\u3002<\/p>\n<p>Assume you have created a new Console Application project named FunWithStrings and added it to your solution. Clear out the existing code and add the following:<br \/>\n\u5047\u8bbe\u60a8\u5df2\u7ecf\u521b\u5efa\u4e86\u4e00\u4e2a\u540d\u4e3a FunWithString \u7684\u65b0\u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u9879\u76ee\uff0c\u5e76\u5c06\u5176\u6dfb\u52a0\u5230\u60a8\u7684\u89e3\u51b3\u65b9\u6848\u4e2d\u3002\u6e05\u9664\u73b0\u6709\u4ee3\u7801\u5e76\u6dfb\u52a0\u4ee5\u4e0b\u5185\u5bb9\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing System.Runtime.CompilerServices;\nusing System.Text;\n\/\/ BasicStringFunctionality();\nstatic void BasicStringFunctionality()\n{\n    Console.WriteLine(&quot;=&gt; Basic String functionality:&quot;);\n    string firstName = &quot;Freddy&quot;;\n    Console.WriteLine(&quot;Value of firstName: {0}&quot;, firstName);\n    Console.WriteLine(&quot;firstName has {0} characters.&quot;, firstName.Length);\n    Console.WriteLine(&quot;firstName in uppercase: {0}&quot;, firstName.ToUpper());\n    Console.WriteLine(&quot;firstName in lowercase: {0}&quot;, firstName.ToLower());\n    Console.WriteLine(&quot;firstName contains the letter y?: {0}&quot;,\n    firstName.Contains(&quot;y&quot;));\n    Console.WriteLine(&quot;New first name: {0}&quot;, firstName.Replace(&quot;dy&quot;, &quot;&quot;));\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>There is not too much to say here, as this method simply invokes various members, such as ToUpper() and Contains(), on a local string variable to yield various formats and transformations. Here is the initial output:<br \/>\n\u8fd9\u91cc\u6ca1\u6709\u592a\u591a\u8981\u8bf4\u7684\uff0c\u56e0\u4e3a\u6b64\u65b9\u6cd5\u53ea\u662f\u8c03\u7528\u5404\u79cd\u6210\u5458\uff0c\u4f8b\u5982 ToUpper\uff08\uff09\u548c Contains\uff08\uff09\uff0c\u5728\u5c40\u90e8\u5b57\u7b26\u4e32\u53d8\u91cf\u4e0a\u751f\u6210\u5404\u79cd\u683c\u5f0f\u548c\u8f6c\u6362\u3002\u4ee5\u4e0b\u662f\u521d\u59cb\u8f93\u51fa\uff1a<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n***** Fun with Strings *****\n=&gt; Basic String functionality:\nValue of firstName: Freddy\nfirstName has 6 characters.\nfirstName in uppercase: FREDDY\nfirstName in lowercase: freddy\nfirstName contains the letter y?: True\nfirstName after replace: Fred\n<\/pre>\n<\/p>\n<p>While this output might not seem too surprising, the output seen via calling the Replace() method is a bit misleading. In reality, the firstName variable has not changed at all; rather, you receive a new string in a modified format. You will revisit the immutable nature of strings in just a few moments.<br \/>\n\u867d\u7136\u6b64\u8f93\u51fa\u53ef\u80fd\u770b\u8d77\u6765\u4e0d\u592a\u4ee4\u4eba\u60ca\u8bb6\uff0c\u4f46\u901a\u8fc7\u8c03\u7528 Replace\uff08\uff09 \u65b9\u6cd5\u770b\u5230\u7684\u8f93\u51fa\u6709\u70b9\u8bef\u5bfc\u3002\u5b9e\u9645\u4e0a\uff0cfirstName \u53d8\u91cf\u6839\u672c\u6ca1\u6709\u6539\u53d8;\u76f8\u53cd\uff0c\u60a8\u4f1a\u6536\u5230\u4e00\u4e2a\u4fee\u6539\u683c\u5f0f\u7684\u65b0\u5b57\u7b26\u4e32\u3002\u60a8\u5c06\u5728\u77ed\u77ed\u51e0\u5206\u949f\u5185\u91cd\u65b0\u5ba1\u89c6\u5b57\u7b26\u4e32\u7684\u4e0d\u53ef\u53d8\u6027\u8d28\u3002<\/p>\n<h2>Performing String Concatenation<\/h2>\n<p>\u6267\u884c\u5b57\u7b26\u4e32\u4e32\u8054<\/p>\n<p>String variables can be connected to build larger strings via the C# + (as well as +=) operator. As you might know, this technique is formally termed string concatenation. Consider the following new helper function:<br \/>\n\u5b57\u7b26\u4e32\u53d8\u91cf\u53ef\u4ee5\u901a\u8fc7 C# +\uff08\u4ee5\u53ca +=\uff09\u8fd0\u7b97\u7b26\u8fde\u63a5\u4ee5\u751f\u6210\u66f4\u5927\u7684\u5b57\u7b26\u4e32\u3002\u60a8\u53ef\u80fd\u77e5\u9053\uff0c\u8fd9\u79cd\u6280\u672f\u6b63\u5f0f\u79f0\u4e3a\u5b57\u7b26\u4e32\u4e32\u8054\u3002\u8bf7\u8003\u8651\u4ee5\u4e0b\u65b0\u7684\u5e2e\u52a9\u7a0b\u5e8f\u51fd\u6570\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void StringConcatenation()\n{\n    Console.WriteLine(&quot;=&gt; String concatenation:&quot;);\n    string s1 = &quot;Programming the &quot;;\n    string s2 = &quot;PsychoDrill (PTP)&quot;;\n    string s3 = s1 + s2;\n    Console.WriteLine(s3);\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>You might be interested to know that the C# + symbol is processed by the compiler to emit a call to the static String.Concat() method. Given this, it is possible to perform string concatenation by calling String. Concat() directly as shown in the following modified version of the method (although you really have not gained anything by doing so\u2014in fact, you have incurred additional keystrokes!):<br \/>\n\u60a8\u53ef\u80fd\u6709\u5174\u8da3\u77e5\u9053 C# + \u7b26\u53f7\u7531\u7f16\u8bd1\u5668\u5904\u7406\u4ee5\u53d1\u51fa\u5bf9\u9759\u6001 String.Concat\uff08\uff09 \u65b9\u6cd5\u7684\u8c03\u7528\u3002\u9274\u4e8e\u6b64\uff0c\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528 String \u6765\u6267\u884c\u5b57\u7b26\u4e32\u8fde\u63a5\u3002Concat\uff08\uff09 \u76f4\u63a5\u5982\u4ee5\u4e0b\u65b9\u6cd5\u7684\u4fee\u6539\u7248\u672c\u6240\u793a\uff08\u5c3d\u7ba1\u60a8\u8fd9\u6837\u505a\u5b9e\u9645\u4e0a\u6ca1\u6709\u4efb\u4f55\u6536\u83b7 - \u4e8b\u5b9e\u4e0a\uff0c\u60a8\u5df2\u7ecf\u4ea7\u751f\u4e86\u989d\u5916\u7684\u51fb\u952e\uff01<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void StringConcatenation()\n{\n    Console.WriteLine(&quot;=&gt; String concatenation:&quot;);\n    string s1 = &quot;Programming the &quot;;\n    string s2 = &quot;PsychoDrill (PTP)&quot;;\n    string s3 = String.Concat(s1, s2);\n    Console.WriteLine(s3);\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<h2>Using Escape Characters<\/h2>\n<p>\u4f7f\u7528\u8f6c\u4e49\u5b57\u7b26<\/p>\n<p>As in other C-based languages, C# string literals may contain various escape characters, which qualify how the character data should be printed to the output stream. Each escape character begins with a backslash, followed by a specific token. In case you are a bit rusty on the meanings behind these escape characters, Table 3-6 lists the more common options.<br \/>\n\u4e0e\u5176\u4ed6\u57fa\u4e8e C \u7684\u8bed\u8a00\u4e00\u6837\uff0cC# \u5b57\u7b26\u4e32\u6587\u672c\u53ef\u80fd\u5305\u542b\u5404\u79cd\u8f6c\u4e49\u5b57\u7b26\uff0c\u8fd9\u4e9b\u5b57\u7b26\u9650\u5b9a\u4e86\u5e94\u5982\u4f55\u5c06\u5b57\u7b26\u6570\u636e\u6253\u5370\u5230\u8f93\u51fa\u6d41\u3002\u6bcf\u4e2a\u8f6c\u4e49\u5b57\u7b26\u90fd\u4ee5\u53cd\u659c\u6760\u5f00\u5934\uff0c\u540e\u8ddf\u4e00\u4e2a\u7279\u5b9a\u7684\u6807\u8bb0\u3002\u5982\u679c\u60a8\u5bf9\u8fd9\u4e9b\u8f6c\u4e49\u5b57\u7b26\u80cc\u540e\u7684\u542b\u4e49\u6709\u70b9\u751f\u758f\uff0c<br \/>\n\u8868 3-6 \u5217\u51fa\u4e86\u66f4\u5e38\u89c1\u7684\u9009\u9879\u3002<\/p>\n<p>Table 3-6. String Literal Escape Characters<br \/>\n\u8868 3-6. \u5b57\u7b26\u4e32\u6587\u672c\u8f6c\u4e49\u5b57\u7b26<\/p>\n<table>\n<tr>\n<td>Character<\/td>\n<td>Meaning in Life<\/td>\n<\/tr>\n<tr>\n<td>\\&#39;<\/td>\n<td>Inserts a single quote into a string literal.<br \/>\n        \u5728\u5b57\u7b26\u4e32\u6587\u672c\u4e2d\u63d2\u5165\u5355\u5f15\u53f7\u3002<\/td>\n<\/tr>\n<tr>\n<td>\\&quot;<\/td>\n<td>Inserts a double quote into a string literal.<br \/>\n        \u5728\u5b57\u7b26\u4e32\u6587\u672c\u4e2d\u63d2\u5165\u53cc\u5f15\u53f7\u3002<\/td>\n<\/tr>\n<tr>\n<td>\\\\<\/td>\n<td>Inserts a backslash into a string literal. This can be quite helpful when defining file or network paths.<br \/>\n        \u5728\u5b57\u7b26\u4e32\u6587\u672c\u4e2d\u63d2\u5165\u53cd\u659c\u6760\u3002\u8fd9\u5728\u5b9a\u4e49\u6587\u4ef6\u6216\u7f51\u7edc\u8def\u5f84\u65f6\u975e\u5e38\u6709\u7528\u3002<\/td>\n<\/tr>\n<tr>\n<td>\\a<\/td>\n<td>Triggers a system alert (beep). For console programs, this can be an audio clue to the user.<br \/>\n        \u89e6\u53d1\u7cfb\u7edf\u8b66\u62a5\uff08\u8702\u9e23\u97f3\uff09\u3002\u5bf9\u4e8e\u63a7\u5236\u53f0\u7a0b\u5e8f\uff0c\u8fd9\u53ef\u4ee5\u662f\u7528\u6237\u7684\u97f3\u9891\u7ebf\u7d22\u3002<\/td>\n<\/tr>\n<tr>\n<td>\\n<\/td>\n<td>Inserts a line feed (Unix-based systems).<br \/>\n        \u63d2\u5165\u6362\u884c\u7b26\uff08\u57fa\u4e8e Unix \u7684\u7cfb\u7edf\uff09\u3002<\/td>\n<\/tr>\n<tr>\n<td>\\r\\n<\/td>\n<td>Inserts a line feed (non-Unix-based platforms).<br \/>\n        \u63d2\u5165\u6362\u884c\u7b26\uff08\u975e\u57fa\u4e8e Unix \u7684\u5e73\u53f0\uff09\u3002<\/td>\n<\/tr>\n<tr>\n<td>\\r<\/td>\n<td>Inserts a carriage return.<br \/>\n        \u63d2\u5165\u56de\u8f66\u7b26\u3002<\/td>\n<\/tr>\n<tr>\n<td>\\t<\/td>\n<td>Inserts a horizontal tab into the string literal.<br \/>\n        \u5728\u5b57\u7b26\u4e32\u6587\u672c\u4e2d\u63d2\u5165\u6c34\u5e73\u5236\u8868\u7b26\u3002<\/td>\n<\/tr>\n<\/table>\n<p>For example, to print a string that contains a tab between each word, you can make use of the \\t escape character. Or assume you want to create a string literal that contains quotation marks, another that defines a directory path, and a final string literal that inserts three blank lines after printing the character data. To do so without compiler errors, you would need to make use of the \\&quot;, \\, and \\n escape characters. The following method demonstrates this:<br \/>\n\u4f8b\u5982\uff0c\u82e5\u8981\u6253\u5370\u6bcf\u4e2a\u5355\u8bcd\u4e4b\u95f4\u5305\u542b\u4e00\u4e2a\u5236\u8868\u7b26\u7684\u5b57\u7b26\u4e32\uff0c\u53ef\u4ee5\u4f7f\u7528 \\t \u8f6c\u4e49\u5b57\u7b26\u3002\u6216\u8005\u5047\u8bbe\u60a8\u8981\u521b\u5efa\u4e00\u4e2a\u5305\u542b\u5f15\u53f7\u7684\u5b57\u7b26\u4e32\u6587\u672c\uff0c\u53e6\u4e00\u4e2a\u5b9a\u4e49\u76ee\u5f55\u8def\u5f84\u548c\u5728\u6253\u5370\u5b57\u7b26\u6570\u636e\u540e\u63d2\u5165\u4e09\u4e2a\u7a7a\u884c\u7684\u6700\u7ec8\u5b57\u7b26\u4e32\u6587\u672c\u3002\u82e5\u8981\u5728\u4e0d\u51fa\u9519\u7684\u60c5\u51b5\u4e0b\u6267\u884c\u6b64\u64cd\u4f5c\uff0c\u9700\u8981\u4f7f\u7528 \\\u201c\u3001\\ \u548c \\n \u8f6c\u4e49\u5b57\u7b26\u3002 \u4ee5\u4e0b\u65b9\u6cd5\u5bf9\u6b64\u8fdb\u884c\u4e86\u6f14\u793a\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void EscapeChars()\n{\n    Console.WriteLine(&quot;=&gt; Escape characters:&quot;);\n    string strWithTabs = &quot;Model\\tColor\\tSpeed\\tPet Name &quot;;\n    Console.WriteLine(strWithTabs);\n    Console.WriteLine(&quot;Everyone loves \\&quot;Hello World\\&quot; &quot;);\n    Console.WriteLine(&quot;C:\\\\MyApp\\\\bin\\\\Debug &quot;);\n    \/\/ Adds a total of 4 blank lines (3 escaped, 1 from WriteLine).\n    \/\/ \u603b\u5171\u6dfb\u52a0 4 \u4e2a\u7a7a\u767d\u884c\uff083 \u4e2a\u8f6c\u4e49\uff0c1 \u4e2a\u6765\u81ea WriteLine\uff09\u3002\n    Console.WriteLine(&quot;All finished.\\n\\n\\n &quot;);\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>Notice from Table 3-6 that there is a difference when creating a new line based on the operating system the code is executing on. The NewLine property of the static Environment type adds in the proper escape code(s) for adding blank lines into your text. Consider the following addition to the EscapeChars() method:<br \/>\n\u8bf7\u6ce8\u610f\uff0c\u4ece\u8868 3-6 \u4e2d\u53ef\u4ee5\u770b\u51fa\uff0c\u6839\u636e\u6267\u884c\u4ee3\u7801\u7684\u64cd\u4f5c\u7cfb\u7edf\u521b\u5efa\u65b0\u884c\u65f6\u5b58\u5728\u5dee\u5f02\u3002\u9759\u6001\u73af\u5883\u7c7b\u578b\u7684 NewLine \u5c5e\u6027\u6dfb\u52a0\u4e86\u6b63\u786e\u7684\u8f6c\u4e49\u4ee3\u7801\uff0c\u7528\u4e8e\u5728\u6587\u672c\u4e2d\u6dfb\u52a0\u7a7a\u767d\u884c\u3002\u8003\u8651\u5bf9 EscapeChars\uff08\uff09 \u65b9\u6cd5\u7684\u4ee5\u4e0b\u8865\u5145\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void EscapeChars()\n{\n    \/\/ omitted for brevity\n    \/\/ \u4e3a\u7b80\u6d01\u8d77\u89c1\u7701\u7565\n    \/\/ Adds a 4 more blank lines.\n    \/\/ \u518d\u6dfb\u52a0 4 \u4e2a\u7a7a\u884c\u3002\n    Console.WriteLine(&quot;All finished for real this time.{0}{0}{0}&quot;, Environment.NewLine);\n}\n<\/pre>\n<\/p>\n<h2>Performing String Interpolation<\/h2>\n<p>\u6267\u884c\u5b57\u7b26\u4e32\u63d2\u503c<\/p>\n<p>The curly-bracket syntax illustrated within this chapter ({0}, {1}, etc.) has existed within the .NET platform since version 1.0. Starting with the release of C# 6, C# programmers can use an alternative syntax to build string literals that contain placeholders for variables. Formally, this is called string interpolation. While the output of the operation is identical to traditional string formatting syntax, this new approach allows you to directly embed the variables themselves, rather than tacking them on as a comma-delimited list.<br \/>\n\u672c\u7ae0\u4e2d\u8bf4\u660e\u7684\u5927\u62ec\u53f7\u8bed\u6cd5\uff08{0}\u3001{1}\u7b49\uff09\u81ea 1.0 \u7248\u8d77\u5c31\u5b58\u5728\u4e8e .NET \u5e73\u53f0\u4e2d\u3002\u4ece C# 6 \u7684\u53d1\u5e03\u5f00\u59cb\uff0cC# \u7a0b\u5e8f\u5458\u53ef\u4ee5\u4f7f\u7528\u66ff\u4ee3\u8bed\u6cd5\u6765\u751f\u6210\u5305\u542b\u53d8\u91cf\u5360\u4f4d\u7b26\u7684\u5b57\u7b26\u4e32\u6587\u672c\u3002\u4ece\u5f62\u5f0f\u4e0a\u8bb2\uff0c\u8fd9\u79f0\u4e3a\u5b57\u7b26\u4e32\u63d2\u503c\u3002\u867d\u7136\u64cd\u4f5c\u7684\u8f93\u51fa\u4e0e\u4f20\u7edf\u7684\u5b57\u7b26\u4e32\u683c\u5f0f\u8bed\u6cd5\u76f8\u540c\uff0c\u4f46\u8fd9\u79cd\u65b0\u65b9\u6cd5\u5141\u8bb8\u60a8\u76f4\u63a5\u5d4c\u5165\u53d8\u91cf\u672c\u8eab\uff0c\u800c\u4e0d\u662f\u5c06\u5b83\u4eec\u4f5c\u4e3a\u9017\u53f7\u5206\u9694\u7684\u5217\u8868\u3002<\/p>\n<p>Consider the following additional method of your Program class (StringInterpolation()), which builds a string variable using each approach:<br \/>\n\u8bf7\u8003\u8651 Program \u7c7b\u7684\u4ee5\u4e0b\u9644\u52a0\u65b9\u6cd5 \uff08StringInterpolation\uff08\uff09\uff09\uff0c\u8be5\u65b9\u6cd5\u4f7f\u7528\u6bcf\u79cd\u65b9\u6cd5\u751f\u6210\u4e00\u4e2a\u5b57\u7b26\u4e32\u53d8\u91cf\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void StringInterpolation()\n{\n    Console.WriteLine(&quot;=&gt; String interpolation:\\a&quot;);\n    \/\/ Some local variables we will plug into our larger string\n    \/\/ \u4e00\u4e9b\u5c40\u90e8\u53d8\u91cf\u6211\u4eec\u5c06\u63d2\u5165\u5230\u8f83\u5927\u7684\u5b57\u7b26\u4e32 int age = 4 \u4e2d;\n    int age = 4;\n    string name = &quot;Soren&quot;;\n    \/\/ Using curly-bracket syntax.\n    \/\/ \u4f7f\u7528\u5927\u62ec\u53f7\u8bed\u6cd5\u3002\n    string greeting = string.Format(&quot;Hello {0} you are {1} years old.&quot;, name, age);\n    Console.WriteLine(greeting);\n    \/\/ Using string interpolation\n    \/\/ \u4f7f\u7528\u5b57\u7b26\u4e32\u5185\u63d2\n    string greeting2 = $&quot;Hello {name} you are {age} years old.&quot;;\n    Console.WriteLine(greeting2);\n}\n<\/pre>\n<\/p>\n<p>In the greeting2 variable, notice how the string you are constructing begins with a dollar sign \uff08$\uff09prefix.Next, notice that the curly brackets still are used to mark a variable placeholder; however, rather than using a numerical tag, you are able to place the variable directly into the scope. The assumed advantage is that this new formatting syntax is a bit easier to read in a linear (left-to-right) fashion, given that you are not required to \u201cjump to the end\u201d to see the list of values to plug in at runtime.<br \/>\n\u5728 greeting2 \u53d8\u91cf\u4e2d\uff0c\u8bf7\u6ce8\u610f\u60a8\u6784\u9020\u7684\u5b57\u7b26\u4e32\u5982\u4f55\u4ee5\u7f8e\u5143\u7b26\u53f7 \uff08$\uff09 \u524d\u7f00\u5f00\u5934\u3002\u63a5\u4e0b\u6765\uff0c\u8bf7\u6ce8\u610f\uff0c\u5927\u62ec\u53f7\u4ecd\u7528\u4e8e\u6807\u8bb0\u53d8\u91cf\u5360\u4f4d\u7b26;\u4f46\u662f\uff0c\u60a8\u53ef\u4ee5\u76f4\u63a5\u5c06\u53d8\u91cf\u653e\u5165\u4f5c\u7528\u57df\u4e2d\uff0c\u800c\u4e0d\u662f\u4f7f\u7528\u6570\u5b57\u6807\u8bb0\u3002\u5047\u5b9a\u7684\u4f18\u70b9\u662f\uff0c\u8fd9\u79cd\u65b0\u7684\u683c\u5f0f\u8bed\u6cd5\u4ee5\u7ebf\u6027\uff08\u4ece\u5de6\u5230\u53f3\uff09\u65b9\u5f0f\u66f4\u5bb9\u6613\u9605\u8bfb\uff0c\u56e0\u4e3a\u60a8\u4e0d\u9700\u8981\u201c\u8df3\u5230\u672b\u5c3e\u201d\u5373\u53ef\u67e5\u770b\u8fd0\u884c\u65f6\u8981\u63d2\u5165\u7684\u503c\u5217\u8868\u3002<\/p>\n<p>There is another interesting aspect of this new syntax: the curly brackets used in string interpolation are a valid scope. Therefore, you can use the dot operation on the variables to change their state. Consider updates to each assembled string variable.<br \/>\n\u8fd9\u79cd\u65b0\u8bed\u6cd5\u8fd8\u6709\u53e6\u4e00\u4e2a\u6709\u8da3\u7684\u65b9\u9762\uff1a\u5b57\u7b26\u4e32\u63d2\u503c\u4e2d\u4f7f\u7528\u7684\u5927\u62ec\u53f7\u662f\u4e00\u4e2a\u6709\u6548\u7684\u8303\u56f4\u3002\u56e0\u6b64\uff0c\u60a8\u53ef\u4ee5\u5bf9\u53d8\u91cf\u4f7f\u7528\u70b9\u8fd0\u7b97\u6765\u66f4\u6539\u5176\u72b6\u6001\u3002\u8bf7\u8003\u8651\u66f4\u65b0\u6bcf\u4e2a\u7ec4\u5408\u7684\u5b57\u7b26\u4e32\u53d8\u91cf\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstring greeting = string.Format(&quot;Hello {0} you are {1} years old.&quot;, name.ToUpper(), age);\nstring greeting2 = $&quot;Hello {name.ToUpper()} you are {age} years old.&quot;;\n<\/pre>\n<\/p>\n<p>Here, I have uppercased the name via a call to ToUpper(). Do note that in the string interpolation approach, you do not add a semicolon terminator when calling this method. Given this, you cannot use the curly-bracket scope as a fully blown method scope that contains numerous lines of executable code. Rather, you can invoke a single member on the object using the dot operator as well as define a simple general expression such as {age += 1}.<br \/>\n\u5728\u8fd9\u91cc\uff0c\u6211\u901a\u8fc7\u8c03\u7528 ToUpper\uff08\uff09 \u5c06\u540d\u79f0\u5927\u5199\u3002\u8bf7\u6ce8\u610f\uff0c\u5728\u5b57\u7b26\u4e32\u5185\u63d2\u65b9\u6cd5\u4e2d\uff0c\u8c03\u7528\u6b64\u65b9\u6cd5\u65f6\u4e0d\u4f1a\u6dfb\u52a0\u5206\u53f7\u7ec8\u6b62\u7b26\u3002\u9274\u4e8e\u6b64\uff0c\u60a8\u4e0d\u80fd\u5c06\u5927\u62ec\u53f7\u4f5c\u7528\u57df\u7528\u4f5c\u5305\u542b\u5927\u91cf\u53ef\u6267\u884c\u4ee3\u7801\u884c\u7684\u5b8c\u5168\u6210\u719f\u7684\u65b9\u6cd5\u4f5c\u7528\u57df\u3002\u76f8\u53cd\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528\u70b9\u8fd0\u7b97\u7b26\u8c03\u7528\u5bf9\u8c61\u4e0a\u7684\u5355\u4e2a\u6210\u5458\uff0c\u4e5f\u53ef\u4ee5\u5b9a\u4e49\u4e00\u4e2a\u7b80\u5355\u7684\u901a\u7528\u8868\u8fbe\u5f0f\uff0c\u4f8b\u5982 {age += 1}\u3002<\/p>\n<p>It is also worth noting that you can still use escape characters in the string literal within this new syntax.Thus, if you wanted to insert a tab, you can prefix a \\t token as so:<br \/>\n\u8fd8\u503c\u5f97\u6ce8\u610f\u7684\u662f\uff0c\u60a8\u4ecd\u7136\u53ef\u4ee5\u5728\u6b64\u65b0\u8bed\u6cd5\u4e2d\u7684\u5b57\u7b26\u4e32\u6587\u672c\u4e2d\u4f7f\u7528\u8f6c\u4e49\u5b57\u7b26\u3002\u56e0\u6b64\uff0c\u5982\u679c\u8981\u63d2\u5165\u5236\u8868\u7b26\uff0c\u53ef\u4ee5\u5728 \\t \u6807\u8bb0\u524d\u9762\u6dfb\u52a0\u5982\u4e0b\u524d\u7f00\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstring greeting = string.Format(&quot;\\tHello {0} you are {1} years old.&quot;, name.ToUpper(), age); \nstring greeting2 = $&quot;\\tHello {name.ToUpper()} you are {age} years old.&quot;;\n<\/pre>\n<\/p>\n<h2>Performance Improvements (Updated 10.0)<\/h2>\n<p>\u6027\u80fd\u6539\u8fdb\uff0810.0 \u66f4\u65b0\uff09<\/p>\n<p>When using string interpolation in versions prior to C# 10, under the hood the compiler is converting the interpolated string statement into a Format() call. For example, take a shortened version of the previous example and plug it into the Main() method of a .NET 5 (C# 9) console application (named CSharp9Strings).<br \/>\n\u5728 C# 10 \u4e4b\u524d\u7684\u7248\u672c\u4e2d\u4f7f\u7528\u5b57\u7b26\u4e32\u5185\u63d2\u65f6\uff0c\u7f16\u8bd1\u5668\u4f1a\u5c06\u5185\u63d2\u5b57\u7b26\u4e32\u8bed\u53e5\u8f6c\u6362\u4e3a Format\uff08\uff09 \u8c03\u7528\u3002\u4f8b\u5982\uff0c\u91c7\u7528\u4e0a\u4e00\u793a\u4f8b\u7684\u7f29\u77ed\u7248\u672c\uff0c\u5e76\u5c06\u5176\u63d2\u5165 .NET 5 \uff08C# 9\uff09 \u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\uff08\u540d\u4e3a CSharp9Strings\uff09\u7684 Main\uff08\uff09 \u65b9\u6cd5\u4e2d\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing System;\nnamespace CSharp9Strings\n{\n    class Program\n    {\n        static void Main(string&#x5B;] args)\n        {\n            int age = 4;\n            string name = &quot;Soren&quot;;\n            string greeting = string.Format(&quot;\\tHello {0} you are {1} years old.&quot;, name.ToUpper(), age);\n            string greetings = $&quot;\\tHello {name.ToUpper()} you are {age} years old.&quot;;\n        }\n    }\n}\n<\/pre>\n<\/p>\n<p>When the Main() method is examined with ILDasm, you can see that both the call to Format() and the string interpolation calls are implemented as the same Format() calls in the IL (lines in bold):<br \/>\n\u5f53\u4f7f\u7528 ILDasm \u68c0\u67e5 Main\uff08\uff09 \u65b9\u6cd5\u65f6\uff0c\u60a8\u53ef\u4ee5\u770b\u5230\u5bf9 Format\uff08\uff09 \u7684\u8c03\u7528\u548c\u5b57\u7b26\u4e32\u5185\u63d2\u8c03\u7528\u90fd\u4f5c\u4e3a IL \u4e2d\u7684\u76f8\u540c Format\uff08\uff09 \u8c03\u7528\u5b9e\u73b0\uff08\u7c97\u4f53\u884c\uff09\uff1a<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n.method private hidebysig static void Main(string&#x5B;] args) cil managed\n{\n    .maxstack 3\n    .entrypoint\n    .locals init (int32 V_0, string V_1, string V_2)\n    IL_0000: nop\n    IL_0001: ldc.i4.4\n    IL_0002: stloc.0\n    IL_0003: ldstr &quot;Soren&quot;\n    IL_0008: stloc.1\n    IL_0009: ldstr &quot;\\tHello {0} you are {1} years old.&quot;\n    IL_000e: ldloc.1\n    IL_000f: callvirt instance string &#x5B;System.Runtime]System.String::ToUpper()\n    IL_0014: ldloc.0\n    IL_0015: box &#x5B;System.Runtime]System.Int32\n    IL_001a: call string &#x5B;System.Runtime]System.String::Format(string, object, object)\n    IL_001f: stloc.2\n    IL_0020: ldstr &quot;\\tHello {0} you are {1} years old.&quot;\n    IL_0025: ldloc.1\n    IL_0026: callvirt instance string &#x5B;System.Runtime]System.String::ToUpper()\n    IL_002b: ldloc.0\n    IL_002c: box &#x5B;System.Runtime]System.Int32\n    IL_0031: call string &#x5B;System.Runtime]System.String::Format(string, object, object)\n    IL_0036: stloc.3\n    IL_0037: ret\n} \/\/ end of method Program::Main\n<\/pre>\n<\/p>\n<p>The problem with this is performance. When Format() is called at runtime, the method parses the format string to find the literals, format items, specifiers, and alignments, which the compiler already did at compile time. All items are passed in as System.Object, which means value types are boxed. If there are more than three parameters, an array is allocated. In addition to performance issues, Format() works only with reference types.<br \/>\n\u8fd9\u6837\u505a\u7684\u95ee\u9898\u662f\u6027\u80fd\u3002\u5728\u8fd0\u884c\u65f6\u8c03\u7528 Format\uff08\uff09 \u65f6\uff0c\u8be5\u65b9\u6cd5\u4f1a\u89e3\u6790\u683c\u5f0f\u5b57\u7b26\u4e32\u4ee5\u67e5\u627e\u6587\u672c\u3001\u683c\u5f0f\u9879\u3001\u8bf4\u660e\u7b26\u548c\u5bf9\u9f50\u65b9\u5f0f\uff0c\u7f16\u8bd1\u5668\u5728\u7f16\u8bd1\u65f6\u5df2\u7ecf\u8fd9\u6837\u505a\u4e86\u3002\u6240\u6709\u9879\u90fd\u4f5c\u4e3a System.Object \u4f20\u5165\uff0c\u8fd9\u610f\u5473\u7740\u503c\u7c7b\u578b\u88ab\u88c5\u7bb1\u3002\u5982\u679c\u6709\u4e09\u4e2a\u4ee5\u4e0a\u7684\u53c2\u6570\uff0c\u5219\u5206\u914d\u4e00\u4e2a\u6570\u7ec4\u3002\u9664\u4e86\u6027\u80fd\u95ee\u9898\u4e4b\u5916\uff0cFormat\uff08\uff09 \u4ec5\u9002\u7528\u4e8e\u5f15\u7528\u7c7b\u578b\u3002<\/p>\n<p>A major change in C# 10 is that all the work that can be done at compile time is retained in the IL using the DefaultInterpolatedStringHandler and its methods. This is the equivalent C# 10 code that interpolated strings are converted to:<br \/>\nC# 10 \u4e2d\u7684\u4e00\u4e2a\u4e3b\u8981\u66f4\u6539\u662f\uff0c\u5728\u7f16\u8bd1\u65f6\u53ef\u4ee5\u5b8c\u6210\u7684\u6240\u6709\u5de5\u4f5c\u90fd\u4f7f\u7528 DefaultInterpolatedStringHandler \u53ca\u5176\u65b9\u6cd5\u4fdd\u7559\u5728 IL \u4e2d\u3002\u8fd9\u662f\u5c06\u5185\u63d2\u5b57\u7b26\u4e32\u8f6c\u6362\u4e3a\u7684\u7b49\u6548 C# 10 \u4ee3\u7801\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing System.Runtime.CompilerServices;\n\nstatic void StringInterpolationWithDefaultInterpolatedStringHandler()\n{\n    Console.WriteLine(&quot;=&gt; String interpolation under the covers:\\a&quot;);\n    int age = 4;\n    string name = &quot;Soren&quot;;\n    var builder = new DefaultInterpolatedStringHandler(3, 2);\n    builder.AppendLiteral(&quot;\\tHello &quot;);\n    builder.AppendFormatted(name);\n    builder.AppendLiteral(&quot; you are &quot;);\n    builder.AppendFormatted(age);\n    builder.AppendLiteral(&quot; years old.&quot;);\n    var greeting = builder.ToStringAndClear();\n    Console.WriteLine(greeting);\n}\n<\/pre>\n<\/p>\n<p>The version of the DefaultInterpolatedStringHandler\u2019s constructor used in this example takes two integers. The first is the number of literals, and the second is the number variables. This enables the instance to make an educated guess as to how much memory to allocate. Literals are added in with the AppendLiteral() method, and variables are added in with the AppendFormatted() method.<br \/>\n\u6b64\u793a\u4f8b\u4e2d\u4f7f\u7528\u7684 DefaultInterpolatedStringHandler \u6784\u9020\u51fd\u6570\u7684\u7248\u672c\u91c7\u7528\u4e24\u4e2a\u6574\u6570\u3002\u7b2c\u4e00\u4e2a\u662f\u6587\u672c\u7684\u6570\u91cf\uff0c\u7b2c\u4e8c\u4e2a\u662f\u6570\u5b57\u53d8\u91cf\u3002\u8fd9\u4f7f\u5b9e\u4f8b\u80fd\u591f\u5bf9\u8981\u5206\u914d\u7684\u5185\u5b58\u91cf\u8fdb\u884c\u6709\u6839\u636e\u7684\u731c\u6d4b\u3002\u6587\u672c\u662f\u7528 AppendLiteral\uff08\uff09 \u65b9\u6cd5\u6dfb\u52a0\u7684\uff0c\u53d8\u91cf\u662f\u7528 AppendFormatted\uff08\uff09 \u65b9\u6cd5\u6dfb\u52a0\u7684\u3002<\/p>\n<p>Bench testing has shown a significant performance improvement in string handling in C# 10 when your code contains string interpolation, which is good news. The really good news is that you don\u2019t have to write all this extra code. The compiler takes care of it all when compiling string interpolation.<br \/>\n\u57fa\u51c6\u6d4b\u8bd5\u663e\u793a\uff0c\u5f53\u4ee3\u7801\u5305\u542b\u5b57\u7b26\u4e32\u63d2\u503c\u65f6\uff0cC# 10 \u4e2d\u7684\u5b57\u7b26\u4e32\u5904\u7406\u6027\u80fd\u663e\u8457\u63d0\u9ad8\uff0c\u8fd9\u662f\u4e2a\u597d\u6d88\u606f\u3002\u771f\u6b63\u7684\u597d\u6d88\u606f\u662f\uff0c\u60a8\u4e0d\u5fc5\u7f16\u5199\u6240\u6709\u8fd9\u4e9b\u989d\u5916\u7684\u4ee3\u7801\u3002\u7f16\u8bd1\u5668\u5728\u7f16\u8bd1\u5b57\u7b26\u4e32\u63d2\u503c\u65f6\u4f1a\u5904\u7406\u6240\u6709\u95ee\u9898\u3002<\/p>\n<h2>Defining Verbatim Strings (Updated 8.0)<\/h2>\n<p>\u5b9a\u4e49\u9010\u5b57\u5b57\u7b26\u4e32\uff088.0 \u66f4\u65b0\uff09<\/p>\n<p>When you prefix a string literal with the @ symbol, you have created what is termed a verbatim string. Using verbatim strings, you disable the processing of a literal\u2019s escape characters and print out a string as is. This can be most useful when working with strings representing directory and network paths. Therefore, rather than making use of \\ escape characters, you can simply write the following: \u5728\u5b57\u7b26\u4e32\u6587\u672c\u524d\u9762\u52a0\u4e0a @ \u7b26\u53f7\u65f6\uff0c\u60a8\u5df2\u7ecf\u521b\u5efa\u4e86\u6240\u8c13\u7684\u9010\u5b57\u5b57\u7b26\u4e32\u3002\u4f7f\u7528\u9010\u5b57\u5b57\u7b26\u4e32\uff0c\u53ef\u4ee5\u7981\u7528\u6587\u672c\u8f6c\u4e49\u5b57\u7b26\u7684\u5904\u7406\uff0c\u5e76\u6309\u539f\u6837\u6253\u5370\u51fa\u5b57\u7b26\u4e32\u3002\u8fd9\u5728\u5904\u7406\u8868\u793a\u76ee\u5f55\u548c\u7f51\u7edc\u8def\u5f84\u7684\u5b57\u7b26\u4e32s \u65f6\u6700\u6709\u7528\u3002\u56e0\u6b64\uff0c\u4e0e\u5176\u4f7f\u7528 \\ \u8f6c\u4e49\u5b57\u7b26\uff0c\u4e0d\u5982\u7b80\u5355\u5730\u7f16\u5199\u4ee5\u4e0b\u5185\u5bb9\uff1a<\/p>\n<p>Also note that verbatim strings can be used to preserve whitespace for strings that flow over multiple lines.<br \/>\n\u53e6\u8bf7\u6ce8\u610f\uff0c\u9010\u5b57\u5b57\u7b26\u4e32\u53ef\u7528\u4e8e\u4fdd\u7559\u6d41\u7ecf\u591a\u884c\u7684\u5b57\u7b26\u4e32\u7684\u7a7a\u683c\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ The following string is printed verbatim, \n\/\/ \u4ee5\u4e0b\u5b57\u7b26\u4e32\u9010\u5b57\u6253\u5370\uff0c\n\/\/ thus all escape characters are displayed. \n\/\/ \u56e0\u6b64\uff0c\u5c06\u663e\u793a\u6240\u6709\u8f6c\u4e49\u5b57\u7b26\u3002Console.WriteLine(@&quot;C:\\MyApp\\bin\\Debug&quot;);\n\/\/ Whitespace is preserved with verbatim strings. \n\/\/ \u7a7a\u683c\u4f7f\u7528\u9010\u5b57\u5b57\u7b26\u4e32\u4fdd\u7559\u3002\nstring myLongString = @&quot;This is a very\nvery\nvery\nlong string&quot;;\nConsole.WriteLine(myLongString);\n<\/pre>\n<\/p>\n<p>Using verbatim strings, you can also directly insert a double quote into a literal string by doubling the token\u3002<br \/>\n\u4f7f\u7528\u9010\u5b57\u9010\u53e5\u5b57\u7b26\u4e32\uff0c\u60a8\u8fd8\u53ef\u4ee5\u901a\u8fc7\u52a0\u500d\u6807\u8bb0\u76f4\u63a5\u5c06\u53cc\u5f15\u53f7\u63d2\u5165\u5230\u6587\u5b57\u5b57\u7b26\u4e32\u4e2d<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nConsole.WriteLine(@&quot;Cerebus said &quot;&quot;Darrr! Pret-ty sun-sets&quot;&quot;&quot;);\n<\/pre>\n<\/p>\n<p>Verbatim strings can also be interpolated strings, by specifying both the interpolation operator ($) and the verbatim operator (@).<br \/>\n\u9010\u5b57\u5b57\u7b26\u4e32\u4e5f\u53ef\u4ee5\u662f\u5185\u63d2\u5b57\u7b26\u4e32\uff0c\u65b9\u6cd5\u662f\u540c\u65f6\u6307\u5b9a\u63d2\u503c\u8fd0\u7b97\u7b26 \uff08$\uff09 \u548c\u9010\u5b57\u8fd0\u7b97\u7b26 \uff08@\uff09\u3002<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstring interp = &quot;interpolation&quot;;\nstring myLongString2 = $@&quot;This is a very\n    very\n        long string with {interp}&quot;;\n<\/pre>\n<\/p>\n<p>New in C# 8, the order does not matter. Using either $@ or @$ will work.<br \/>\nC# 8 \u4e2d\u7684\u65b0\u529f\u80fd\uff0c\u987a\u5e8f\u65e0\u5173\u7d27\u8981\u3002\u4f7f\u7528 $@ \u6216 @$ \u90fd\u53ef\u4ee5\u3002<\/p>\n<h2>Working with Strings and Equality<\/h2>\n<p>\u4f7f\u7528\u5b57\u7b26\u4e32\u548c\u76f8\u7b49<\/p>\n<p>As will be fully explained in Chapter 4, a reference type is an object allocated on the garbage-collected managed heap. By default, when you perform a test for equality on reference types (via the C# == and != operators), you will be returned true if the references are pointing to the same object in memory. However, even though the string data type is indeed a reference type, the equality operators have been redefined to compare the values of string objects, not the object in memory to which they refer.<br \/>\n\u6b63\u5982\u5c06\u5728\u7b2c4\u7ae0\u4e2d\u5145\u5206\u89e3\u91ca\u7684\u90a3\u6837\uff0c\u5f15\u7528\u7c7b\u578b\u662f\u5728\u5783\u573e\u56de\u6536\u7684\u6258\u7ba1\u5806\u4e0a\u5206\u914d\u7684\u5bf9\u8c61\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u5bf9\u5f15\u7528\u7c7b\u578b\u6267\u884c\u76f8\u7b49\u6027\u6d4b\u8bd5\uff08\u901a\u8fc7 C# == \u548c \uff01= \u8fd0\u7b97\u7b26\uff09\u65f6\uff0c\u5982\u679c\u5f15\u7528\u6307\u5411\u5185\u5b58\u4e2d\u7684\u540c\u4e00\u5bf9\u8c61\uff0c\u5219\u5c06\u8fd4\u56de true\u3002\u4f46\u662f\uff0c\u5373\u4f7f\u5b57\u7b26\u4e32\u6570\u636e\u7c7b\u578b\u786e\u5b9e\u662f\u5f15\u7528\u7c7b\u578b\uff0c\u4e5f\u5df2\u91cd\u65b0\u5b9a\u4e49\u76f8\u7b49\u8fd0\u7b97\u7b26\u4ee5\u6bd4\u8f83\u5b57\u7b26\u4e32\u5bf9\u8c61\u7684\u503c\uff0c\u800c\u4e0d\u662f\u5b83\u4eec\u5f15\u7528\u7684\u5185\u5b58\u4e2d\u7684\u5bf9\u8c61\u3002<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void StringEquality()\n{\n    Console.WriteLine(&quot;=&gt; String equality:&quot;);\n    string s1 = &quot;Hello!&quot;;\n    string s2 = &quot;Yo!&quot;;\n    Console.WriteLine(&quot;s1 = {0}&quot;, s1);\n    Console.WriteLine(&quot;s2 = {0}&quot;, s2);\n    Console.WriteLine();\n\n    \/\/ Test these strings for equality.\n    \/\/ \u6d4b\u8bd5\u8fd9\u4e9b\u5b57\u7b26\u4e32\u7684\u76f8\u7b49\u6027\u3002\n    Console.WriteLine(&quot;s1 == s2: {0}&quot;, s1 == s2);\n    Console.WriteLine(&quot;s1 == Hello!: {0}&quot;, s1 == &quot;Hello!&quot;);\n    Console.WriteLine(&quot;s1 == HELLO!: {0}&quot;, s1 == &quot;HELLO!&quot;);\n    Console.WriteLine(&quot;s1 == hello!: {0}&quot;, s1 == &quot;hello!&quot;);\n    Console.WriteLine(&quot;s1.Equals(s2): {0}&quot;, s1.Equals(s2));\n    Console.WriteLine(&quot;Yo!.Equals(s2): {0}&quot;, &quot;Yo!&quot;.Equals(s2));\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>The C# equality operators by default perform a case-sensitive, culture-insensitive, character-by- character equality test on string objects. Therefore, &quot;Hello!&quot; is not equal to &quot;HELLO!&quot;, which is also different from &quot;hello!&quot;. Also, keeping the connection between string and System.String in mind, notice that you are able to test for equality using the Equals() method of String as well as the baked-in equality operators. Finally, given that every string literal (such as &quot;Yo!&quot;) is a valid System.String instance, you are able to access string-centric functionality from a fixed sequence of characters.<br \/>\n\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cC# \u76f8\u7b49\u8fd0\u7b97\u7b26\u5bf9\u5b57\u7b26\u4e32\u5bf9\u8c61\u6267\u884c\u533a\u5206\u5927\u5c0f\u5199\u3001\u4e0d\u533a\u5206\u533a\u57df\u6027\u3001\u9010\u5b57\u7b26\u76f8\u7b49\u6027\u6d4b\u8bd5\u3002\u56e0\u6b64\uff0c\u201c\u4f60\u597d\uff01 \u4e0d\u7b49\u4e8e\u201c\u4f60\u597d\uff01\u201d\uff0c\u8fd9\u4e5f\u4e0d\u540c\u4e8e\u201c\u4f60\u597d\uff01\u201d\u3002\u6b64\u5916\uff0c\u8bf7\u8bb0\u4f4f\u5b57\u7b26\u4e32\u548c System.String \u4e4b\u95f4\u7684\u8054\u7cfb\uff0c\u8bf7\u6ce8\u610f\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528 String \u7684 Equals\uff08\uff09 \u65b9\u6cd5\u4ee5\u53ca\u5185\u7f6e\u7684\u76f8\u7b49\u8fd0\u7b97\u7b26\u6765\u6d4b\u8bd5\u76f8\u7b49\u6027\u3002\u6700\u540e\uff0c\u5047\u8bbe\u6bcf\u4e2a\u5b57\u7b26\u4e32\u6587\u672c\uff08\u5982\u201cYo\uff01\u201d\uff09\u90fd\u662f\u6709\u6548\u7684 System.String \u5b9e\u4f8b\uff0c\u60a8\u53ef\u4ee5\u4ece\u56fa\u5b9a\u7684\u5b57\u7b26\u5e8f\u5217\u8bbf\u95ee\u4ee5\u5b57\u7b26\u4e32\u4e3a\u4e2d\u5fc3\u7684\u529f\u80fd\u3002<\/p>\n<h2>Modifying String Comparison Behavior<\/h2>\n<p>\u4fee\u6539\u5b57\u7b26\u4e32\u6bd4\u8f83\u884c\u4e3a<\/p>\n<p>As mentioned, the string equality operators (Compare(), Equals(), and ==) as well as the IndexOf() function are by default case sensitive and culture insensitive. This can cause a problem if your program does not care about case. One way to overcome this is to convert everything to uppercase or lowercase and then compare, like this:<br \/>\n\u5982\u524d\u6240\u8ff0\uff0c\u5b57\u7b26\u4e32\u76f8\u7b49\u8fd0\u7b97\u7b26\uff08Compare\uff08\uff09\u3001Equals\uff08\uff09 \u548c ==\uff09\u4ee5\u53ca IndexOf\uff08\uff09 \u51fd\u6570\u9ed8\u8ba4\u533a\u5206\u5927\u5c0f\u5199\uff0c\u533a\u57df\u6027\u4e0d\u533a\u5206\u3002\u5982\u679c\u60a8\u7684\u7a0b\u5e8f\u4e0d\u5173\u5fc3\u5927\u5c0f\u5199\uff0c\u8fd9\u53ef\u80fd\u4f1a\u5bfc\u81f4\u95ee\u9898\u3002\u514b\u670d\u6b64\u95ee\u9898\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\u5c06\u6240\u6709\u5185\u5bb9\u8f6c\u6362\u4e3a\u5927\u5199\u6216\u5c0f\u5199\uff0c\u7136\u540e\u8fdb\u884c\u6bd4\u8f83\uff0c\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nif (firstString.ToUpper() == secondString.ToUpper())\n{\n    \/\/Do something\u505a\u70b9\u4ec0\u4e48\n}\n<\/pre>\n<\/p>\n<p>This makes a copy of each string with all lowercase letters. It is probably not an issue in most cases but could be a performance hit with a significantly large string or even fail based on culture. A much better practice is to use the overloads of the methods listed earlier that take a value of the StringComparison enumeration to control exactly how the comparisons are done. Table 3-7 describes the StringComparison values.<br \/>\n\u8fd9\u5c06\u521b\u5efa\u5305\u542b\u6240\u6709\u5c0f\u5199\u5b57\u6bcd\u7684\u6bcf\u4e2a\u5b57\u7b26\u4e32\u7684\u526f\u672c\u3002\u5728\u5927\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u8fd9\u53ef\u80fd\u4e0d\u662f\u95ee\u9898\uff0c\u4f46\u53ef\u80fd\u662f\u5b57\u7b26\u4e32\u975e\u5e38\u5927\u7684\u5b57\u7b26\u4e32\u5bf9\u6027\u80fd\u7684\u5f71\u54cd\uff0c\u751a\u81f3\u57fa\u4e8e\u533a\u57df\u6027\u800c\u5931\u8d25\u3002\u66f4\u597d\u7684\u505a\u6cd5\u662f\u4f7f\u7528\u524d\u9762\u5217\u51fa\u7684\u65b9\u6cd5\u7684\u91cd\u8f7d\uff0c\u8fd9\u4e9b\u65b9\u6cd5\u7684\u503c\u4e3aStringComparison \u679a\u4e3e\uff0c\u7528\u4e8e\u51c6\u786e\u63a7\u5236\u5982\u4f55\u5b8c\u6210\u6bd4\u8f83\u3002\u8868 3-7 \u4ecb\u7ecd\u4e86\u5b57\u7b26\u4e32\u6bd4\u8f83\u503c\u3002<\/p>\n<p>Table 3-7. Values of the StringComparison Enumeration<br \/>\n\u8868 3-7. \u5b57\u7b26\u4e32\u6bd4\u8f83\u679a\u4e3e\u7684\u503c<\/p>\n<table>\n<tr>\n<td>C# Equality\/Relational Operator<\/td>\n<td>Meaning in Life<\/td>\n<\/tr>\n<tr>\n<td>CurrentCulture<\/td>\n<td>Compares strings using culture-sensitive sort rules and the current culture<br \/>\n        \u4f7f\u7528\u533a\u5206\u533a\u57df\u6027\u7684\u6392\u5e8f\u89c4\u5219\u548c\u5f53\u524d\u533a\u57df\u6027\u6bd4\u8f83\u5b57\u7b26\u4e32<\/td>\n<\/tr>\n<tr>\n<td>CurrentCultureIgnoreCase<\/td>\n<td>Compares strings using culture-sensitive sort rules and the current culture and ignores the case of the strings being compared<br \/>\n        \u4f7f\u7528\u533a\u5206\u533a\u57df\u6027\u7684\u6392\u5e8f\u89c4\u5219\u548c\u5f53\u524d\u533a\u57df\u6027\u6bd4\u8f83\u5b57\u7b26\u4e32\uff0c\u5e76\u5ffd\u7565\u8981\u6bd4\u8f83\u7684\u5b57\u7b26\u4e32\u7684\u5927\u5c0f\u5199<\/td>\n<\/tr>\n<tr>\n<td>InvariantCulture<\/td>\n<td>Compares strings using culture-sensitive sort rules and the invariant culture<br \/>\n        \u4f7f\u7528\u533a\u5206\u533a\u57df\u6027\u7684\u6392\u5e8f\u89c4\u5219\u548c\u56fa\u5b9a\u533a\u57df\u6027\u6bd4\u8f83\u5b57\u7b26\u4e32<\/td>\n<\/tr>\n<tr>\n<td>InvariantCultureIgnoreCase<\/td>\n<td>Compares strings using culture-sensitive sort rules and the invariant culture and ignores the case of the strings being compared<br \/>\n        \u4f7f\u7528\u533a\u5206\u533a\u57df\u6027\u7684\u6392\u5e8f\u89c4\u5219\u548c\u56fa\u5b9a\u533a\u57df\u6027\u6bd4\u8f83\u5b57\u7b26\u4e32\uff0c\u5e76\u5ffd\u7565\u8981\u6bd4\u8f83\u7684\u5b57\u7b26\u4e32\u7684\u5927\u5c0f\u5199<\/td>\n<\/tr>\n<tr>\n<td>Ordinal<\/td>\n<td>Compares strings using ordinal (binary) sort rules<br \/>\n        \u4f7f\u7528\u5e8f\u53f7\uff08\u4e8c\u8fdb\u5236\uff09\u6392\u5e8f\u89c4\u5219\u6bd4\u8f83\u5b57\u7b26\u4e32<\/td>\n<\/tr>\n<tr>\n<td>OrdinalIgnoreCare<\/td>\n<td>Compares strings using ordina<br \/>\n        \u4f7f\u7528\u5e8f\u53f7\uff08\u4e8c\u8fdb\u5236\uff09\u6392\u5e8f\u89c4\u5219\u6bd4\u8f83\u5b57\u7b26\u4e32\uff0c\u5e76\u5ffd\u7565\u8981\u6bd4\u8f83\u7684\u5b57\u7b26\u4e32\u7684\u5927\u5c0f\u5199<\/td>\n<\/tr>\n<\/table>\n<p>To see the effect of using the StringComparison option, create a new method named StringEqualitySpecifyingCompareRules() and add the following code:<br \/>\n\u82e5\u8981\u67e5\u770b\u4f7f\u7528\u201c\u5b57\u7b26\u4e32\u6bd4\u8f83\u201d\u9009\u9879\u7684\u6548\u679c\uff0c\u8bf7\u521b\u5efa\u4e00\u4e2a\u540d\u4e3aStringEqualSpecifyingCompareRules\uff08\uff09 \u5e76\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void StringEqualitySpecifyingCompareRules()\n{\n    Console.WriteLine(&quot;=&gt; String equality (Case Insensitive:&quot;);\n    string s1 = &quot;Hello!&quot;;\n    string s2 = &quot;HELLO!&quot;;\n    Console.WriteLine(&quot;s1 = {0}&quot;, s1);\n    Console.WriteLine(&quot;s2 = {0}&quot;, s2);\n    Console.WriteLine();\n    \/\/ Check the results of changing the default compare rules.\n    \/\/ \u68c0\u67e5\u66f4\u6539\u9ed8\u8ba4\u6bd4\u8f83\u89c4\u5219\u7684\u7ed3\u679c\u3002\n    Console.WriteLine(&quot;Default rules: s1={0},s2={1}s1.Equals(s2): {2}&quot;, s1, s2, s1.Equals(s2));\n    Console.WriteLine(&quot;Ignore case: s1.Equals(s2, StringComparison.OrdinalIgnoreCase): {0}&quot;,\n    s1.Equals(s2, StringComparison.OrdinalIgnoreCase));\n    Console.WriteLine(&quot;Ignore case, Invariant Culture: s1.Equals(s2, StringComparison.InvariantCultureIgnoreCase): {0}&quot;, s1.Equals(s2, StringComparison.InvariantCultureIgnoreCase));\n    Console.WriteLine();\n    Console.WriteLine(&quot;Default rules: s1={0},s2={1} s1.IndexOf(\\&quot;E\\&quot;): {2}&quot;, s1, s2, s1.IndexOf(&quot;E&quot;));\n    Console.WriteLine(&quot;Ignore case: s1.IndexOf(\\&quot;E\\&quot;, StringComparison.OrdinalIgnoreCase): {0}&quot;, s1.IndexOf(&quot;E&quot;, StringComparison.OrdinalIgnoreCase));\n    Console.WriteLine(&quot;Ignore case, Invariant Culture: s1.IndexOf(\\&quot;E\\&quot;, StringComparison.InvariantCultureIgnoreCase): {0}&quot;, s1.IndexOf(&quot;E&quot;, StringComparison.InvariantCultureIgnoreCase));\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>While the examples here are simple ones and use the same letters across most cultures, if your application needed to consider different culture sets, using the StringComparison options is a must.<br \/>\n\u867d\u7136\u6b64\u5904\u7684\u793a\u4f8b\u5f88\u7b80\u5355\uff0c\u5e76\u4e14\u5728\u5927\u591a\u6570\u533a\u57df\u6027\u4e2d\u4f7f\u7528\u76f8\u540c\u7684\u5b57\u6bcd\uff0c\u4f46\u5982\u679c\u5e94\u7528\u7a0b\u5e8f\u9700\u8981\u8003\u8651\u4e0d\u540c\u7684\u533a\u57df\u6027\u96c6\uff0c\u5219\u5fc5\u987b\u4f7f\u7528 StringCompare \u9009\u9879\u3002<\/p>\n<h2>Strings Are Immutable<\/h2>\n<p>\u5b57\u7b26\u4e32\u662f\u4e0d\u53ef\u53d8\u7684<\/p>\n<p>One of the interesting aspects of System.String is that after you assign a string object with its initial value, the character data cannot be changed. At first glance, this might seem like a flat-out lie, given that you are always reassigning strings to new values and because the System.String type defines a number of methods that appear to modify the character data in one way or another (such as uppercasing and lowercasing).However, if you look more closely at what is happening behind the scenes, you will notice the methods of thestring type are, in fact, returning you a new string object in a modified format.<br \/>\nSystem.String \u7684\u4e00\u4e2a\u6709\u8da3\u7684\u65b9\u9762\u662f\uff0c\u5728\u4e3a\u5b57\u7b26\u4e32\u5bf9\u8c61\u5206\u914d\u5176\u521d\u59cb\u503c\u540e\uff0c\u65e0\u6cd5\u66f4\u6539\u5b57\u7b26\u6570\u636e\u3002\u4e4d\u4e00\u770b\uff0c\u8fd9\u4f3c\u4e4e\u662f\u4e00\u4e2a\u5f7b\u5934\u5f7b\u5c3e\u7684\u8c0e\u8a00\uff0c\u56e0\u4e3a\u60a8\u603b\u662f\u5c06\u5b57\u7b26\u4e32\u91cd\u65b0\u5206\u914d\u7ed9\u65b0\u503c\uff0c\u5e76\u4e14\u56e0\u4e3a System.String \u7c7b\u578b\u5b9a\u4e49\u4e86\u8bb8\u591a\u4f3c\u4e4e\u4ee5\u67d0\u79cd\u65b9\u5f0f\u4fee\u6539\u5b57\u7b26\u6570\u636e\u7684\u65b9\u6cd5\uff08\u4f8b\u5982\u5927\u5199\u548c\u5c0f\u5199\uff09\u3002\u4f46\u662f\uff0c\u5982\u679c\u60a8\u66f4\u4ed4\u7ec6\u5730\u89c2\u5bdf\u5e55\u540e\u53d1\u751f\u7684\u4e8b\u60c5\uff0c\u60a8\u4f1a\u6ce8\u610f\u5230\u5b9e\u9645\u4e0a\uff0c\u5b57\u7b26\u4e32\u7c7b\u578b\u4ee5\u4fee\u6539\u540e\u7684\u683c\u5f0f\u8fd4\u56de\u4e00\u4e2a\u65b0\u7684\u5b57\u7b26\u4e32\u5bf9\u8c61\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void StringsAreImmutable()\n{\n    Console.WriteLine(&quot;=&gt; Immutable Strings:\\a&quot;);\n\n    \/\/ Set initial string value.\n    \/\/ \u8bbe\u7f6e\u521d\u59cb\u5b57\u7b26\u4e32\u503c\u3002\n    string s1 = &quot;This is my string.&quot;;\n    Console.WriteLine(&quot;s1 = {0}&quot;, s1);\n\n    \/\/ Uppercase s1?\n    \/\/ \u5927\u5199 s1\uff1f\n    string upperString = s1.ToUpper();\n    Console.WriteLine(&quot;upperString = {0}&quot;, upperString);\n\n    \/\/ Nope! s1 is in the same format!\n    \/\/\u4e0d\uff01S1 \u7684\u683c\u5f0f\u76f8\u540c\uff01\n    Console.WriteLine(&quot;s1 = {0}&quot;, s1);\n}\n<\/pre>\n<\/p>\n<p>If you examine the relevant output that follows, you can verify that the original string object (s1) is not uppercased when calling ToUpper(). Rather, you are returned a copy of the string in a modified format.<br \/>\n\u5982\u679c\u68c0\u67e5\u4e0b\u9762\u7684\u76f8\u5173\u8f93\u51fa\uff0c\u5219\u53ef\u4ee5\u9a8c\u8bc1\u5728\u8c03\u7528 ToUpper\uff08\uff09 \u65f6\u539f\u59cb\u5b57\u7b26\u4e32\u5bf9\u8c61 \uff08s1\uff09 \u662f\u5426\u4e0d\u5927\u5199\u3002\u76f8\u53cd\uff0c\u5c06\u8fd4\u56de\u4fee\u6539\u683c\u5f0f\u7684\u5b57\u7b26\u4e32\u526f\u672c\u3002<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ns1 = This is my string.\nupperString = THIS IS MY STRING.\ns1 = This is my string.\n<\/pre>\n<\/p>\n<p>The same law of immutability holds true when you use the C# assignment operator. To illustrate, implement the following StringsAreImmutable2() method:<br \/>\n\u4f7f\u7528 C# \u8d4b\u503c\u8fd0\u7b97\u7b26\u65f6\uff0c\u76f8\u540c\u7684\u4e0d\u53d8\u6027\u5b9a\u5f8b\u4e5f\u9002\u7528\u3002\u4e3a\u4e86\u8bf4\u660e\u8fd9\u4e00\u70b9\uff0c\u8bf7\u5b9e\u73b0\u4ee5\u4e0b StringsAreImmutable2\uff08\uff09 \u65b9\u6cd5\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void StringsAreImmutable2()\n{\n    Console.WriteLine(&quot;=&gt; Immutable Strings 2:\\a&quot;);\n    string s2 = &quot;My other string&quot;;\n    s2 = &quot;New string value&quot;;\n    Console.WriteLine(s2);\n}\n<\/pre>\n<\/p>\n<p>Now, compile your application and run ildasm.exe (see Chapter 1). The following output shows what you would find if you were to generate CIL code for the StringsAreImmutable2() method:<br \/>\n\u73b0\u5728\uff0c\u7f16\u8bd1\u60a8\u7684\u5e94\u7528\u7a0b\u5e8f\u5e76\u8fd0\u884c ildasm.exe\uff08\u8bf7\u53c2\u9605\u7b2c 1 \u7ae0\uff09\u3002\u4ee5\u4e0b\u8f93\u51fa\u663e\u793a\u4e86\u5982\u679c\u8981\u4e3a StringsAreImmutable2\uff08\uff09 \u65b9\u6cd5\u751f\u6210 CIL \u4ee3\u7801\u65f6\u4f1a\u53d1\u73b0\u7684\u5185\u5bb9\uff1a<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n.method assembly hidebysig static void '&lt;&lt;Main&gt;$&gt;g__StringsAreImmutable2()|0,8'() cil managed\n{\n\/\/ Code size 32 (0x20)\n.maxstack 1\n.locals init (string V_0)\nIL_0000: nop\n...\nIL_000c: ldstr &quot;My other string&quot;\nIL_0011: stloc.0\nIL_0012: ldstr &quot;New string value&quot;\nIL_0017: stloc.0\nIL_0018: ldloc.0\nIL_0013: nop\n...\nIL_0014: ret\n} \/\/ end of method Program::StringsAreImmutable2\n<\/pre>\n<\/p>\n<p>Although you have yet to examine the low-level details of the CIL, note the two calls to the ldstr (load string) opcode. Simply put, the ldstr opcode of the CIL loads a new string object on the managed heap. The previous string object that contained the value &quot;My other string&quot; will eventually be garbage collected.<br \/>\n\u5c3d\u7ba1\u60a8\u5c1a\u672a\u68c0\u67e5 CIL \u7684\u4f4e\u7ea7\u8be6\u7ec6\u4fe1\u606f\uff0c\u4f46\u8bf7\u6ce8\u610f\u5bf9 ldstr\uff08\u52a0\u8f7d\u5b57\u7b26\u4e32\uff09\u64cd\u4f5c\u7801\u7684\u4e24\u6b21\u8c03\u7528\u3002\u7b80\u5355\u5730\u8bf4\uff0cCIL \u7684 ldstr \u64cd\u4f5c\u7801\u5728\u6258\u7ba1\u5806\u4e0a\u52a0\u8f7d\u4e00\u4e2a\u65b0\u7684\u5b57\u7b26\u4e32\u5bf9\u8c61\u3002\u5305\u542b\u503c\u201c\u6211\u7684\u5176\u4ed6\u5b57\u7b26\u4e32\u201d\u7684\u4e0a\u4e00\u4e2a\u5b57\u7b26\u4e32\u5bf9\u8c61\u6700\u7ec8\u5c06\u88ab\u5783\u573e\u56de\u6536\u3002<\/p>\n<p>So, what exactly are you to gather from this insight? In a nutshell, the string class can be inefficient and result in bloated code if misused, especially when performing string concatenation or working with huge amounts of text data. If you need to represent basic character data such as a US Social Security number, first or last names, or simple bits of text used within your application, the string class is the perfect choice.<br \/>\n\u90a3\u4e48\uff0c\u4f60\u7a76\u7adf\u8981\u4ece\u8fd9\u4e2a\u89c1\u89e3\u4e2d\u6536\u96c6\u4ec0\u4e48\uff1f\u7b80\u800c\u8a00\u4e4b\uff0c\u5b57\u7b26\u4e32\u7c7b\u53ef\u80fd\u6548\u7387\u4f4e\u4e0b\uff0c\u5982\u679c\u4f7f\u7528\u4e0d\u5f53\u4f1a\u5bfc\u81f4\u4ee3\u7801\u81c3\u80bf\uff0c\u5c24\u5176\u662f\u5728\u6267\u884c\u5b57\u7b26\u4e32\u8fde\u63a5\u6216\u5904\u7406\u5927\u91cf\u6587\u672c\u6570\u636e\u65f6\u3002\u5982\u679c\u9700\u8981\u8868\u793a\u57fa\u672c\u5b57\u7b26\u6570\u636e\uff08\u5982\u7f8e\u56fd\u793e\u4f1a\u4fdd\u9669\u53f7\u3001\u540d\u5b57\u6216\u59d3\u6c0f\u6216\u5e94\u7528\u7a0b\u5e8f\u4e2d\u4f7f\u7528\u7684\u7b80\u5355\u6587\u672c\u4f4d\uff09\uff0c\u5219\u5b57\u7b26\u4e32\u7c7b\u662f\u5b8c\u7f8e\u7684\u9009\u62e9\u3002<\/p>\n<p>However, if you are building an application that makes heavy use of frequently changing textual data (such as a word processing program), it would be a bad idea to represent the word processing data using string objects, as you will most certainly (and often indirectly) end up making unnecessary copies of string data. So, what is a programmer to do? Glad you asked.<br \/>\n\u4f46\u662f\uff0c\u5982\u679c\u60a8\u6b63\u5728\u6784\u5efa\u5927\u91cf\u4f7f\u7528\u9891\u7e41\u66f4\u6539\u7684\u6587\u672c\u6570\u636e\uff08\u5982\u6587\u5b57\u5904\u7406\u7a0b\u5e8f\uff09\u7684\u5e94\u7528\u7a0b\u5e8f\uff0c\u5219\u4f7f\u7528\u5b57\u7b26\u4e32\u5bf9\u8c61\u8868\u793a\u6587\u5b57\u5904\u7406\u6570\u636e\u5c06\u662f\u4e00\u4e2a\u574f\u4e3b\u610f\uff0c\u56e0\u4e3a\u60a8\u80af\u5b9a\u4f1a\uff08\u901a\u5e38\u662f\u95f4\u63a5\u5730\uff09\u6700\u7ec8\u5236\u4f5c\u4e0d\u5fc5\u8981\u7684\u5b57\u7b26\u4e32\u6570\u636e\u526f\u672c\u3002\u90a3\u4e48\uff0c\u7a0b\u5e8f\u5458\u8be5\u600e\u4e48\u505a\u5462\uff1f\u5f88\u9ad8\u5174\u4f60\u95ee\u3002<\/p>\n<h2>Using the System.Text.StringBuilder Type<\/h2>\n<p>\u4f7f\u7528 System.Text.StringBuilder \u7c7b\u578b<\/p>\n<p>Given that the string type can be inefficient when used with reckless abandon, the .NET Core base class libraries provide the System.Text namespace. Within this (relatively small) namespace lives a class named StringBuilder. Like the System.String class, the StringBuilder defines methods that allow you to replace or format segments, for example. When you want to use this type in your C# code files, your first step is to make sure the following namespace is imported into your code file (this should already be the case for a new Visual Studio project):<br \/>\n\u9274\u4e8e\u5b57\u7b26\u4e32\u7c7b\u578b\u5728\u9c81\u83bd\u653e\u5f03\u4f7f\u7528\u65f6\u53ef\u80fd\u6548\u7387\u4f4e\u4e0b\uff0c.NET Core \u57fa\u7c7b\u5e93\u63d0\u4f9b\u4e86 System.Text \u547d\u540d\u7a7a\u95f4\u3002\u5728\u8fd9\u4e2a\uff08\u76f8\u5bf9\u8f83\u5c0f\u7684\uff09\u547d\u540d\u7a7a\u95f4\u4e2d\uff0c\u6709\u4e00\u4e2a\u540d\u4e3a StringBuilder \u7684\u7c7b\u3002\u4f8b\u5982\uff0c\u4e0e System.String \u7c7b\u4e00\u6837\uff0cStringBuilder \u5b9a\u4e49\u4e86\u5141\u8bb8\u60a8\u66ff\u6362\u6216\u683c\u5f0f\u5316\u6bb5\u7684\u65b9\u6cd5\u3002\u5982\u679c\u8981\u5728 C# \u4ee3\u7801\u6587\u4ef6\u4e2d\u4f7f\u7528\u6b64\u7c7b\u578b\uff0c\u7b2c\u4e00\u6b65\u662f\u786e\u4fdd\u5c06\u4ee5\u4e0b\u547d\u540d\u7a7a\u95f4\u5bfc\u5165\u5230\u4ee3\u7801\u6587\u4ef6\u4e2d\uff08\u5bf9\u4e8e\u65b0\u7684 Visual Studio \u9879\u76ee\uff0c\u5e94\u8be5\u5df2\u7ecf\u5982\u6b64\uff09\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ StringBuilder lives here! \n\/\/ StringBuilder\u4f4f\u5728\u8fd9\u91cc\uff01\nusing System.Text;\n<\/pre>\n<\/p>\n<p>What is unique about the StringBuilder is that when you call members of this type, you are directly modifying the object\u2019s internal character data (making it more efficient), not obtaining a copy of the data in a modified format. When you create an instance of the StringBuilder, you can supply the object\u2019s initial startup values via one of many constructors. If you are new to the topic of constructors, simply understand that constructors allow you to create an object with an initial state when you apply the new keyword.<br \/>\nStringBuilder \u7684\u72ec\u7279\u4e4b\u5904\u5728\u4e8e\uff0c\u5f53\u60a8\u8c03\u7528\u6b64\u7c7b\u578b\u7684\u6210\u5458\u65f6\uff0c\u60a8\u76f4\u63a5\u4fee\u6539\u5bf9\u8c61\u7684\u5185\u90e8\u5b57\u7b26\u6570\u636e\uff08\u4f7f\u5176\u66f4\u6709\u6548\uff09\uff0c\u800c\u4e0d\u662f\u4ee5\u4fee\u6539\u7684\u683c\u5f0f\u83b7\u53d6\u6570\u636e\u7684\u526f\u672c\u3002\u521b\u5efa StringBuilder \u7684\u5b9e\u4f8b\u65f6\uff0c\u53ef\u4ee5\u901a\u8fc7\u591a\u4e2a\u6784\u9020\u51fd\u6570\u4e4b\u4e00\u63d0\u4f9b\u5bf9\u8c61\u7684\u521d\u59cb\u542f\u52a8\u503c\u3002\u5982\u679c\u60a8\u4e0d\u719f\u6089\u6784\u9020\u51fd\u6570\u4e3b\u9898\uff0c\u53ea\u9700\u4e86\u89e3\u6784\u9020\u51fd\u6570\u5141\u8bb8\u60a8\u5728\u5e94\u7528 new \u5173\u952e\u5b57\u65f6\u521b\u5efa\u5177\u6709\u521d\u59cb\u72b6\u6001\u7684\u5bf9\u8c61\u3002Consider the following usage of StringBuilder: \u8003\u8651\u4ee5\u4e0b StringBuilder \u7528\u6cd5\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing System.Text;\n\/\/ FunWithStringBuilder();\nstatic void FunWithStringBuilder()\n{\n    Console.WriteLine(&quot;=&gt; Using the StringBuilder:&quot;);\n    StringBuilder sb = new StringBuilder(&quot;**** Fantastic Games ****&quot;);\n    sb.Append(&quot;\\n&quot;);\n    sb.AppendLine(&quot;Half Life&quot;);\n    sb.AppendLine(&quot;Morrowind&quot;);\n    sb.AppendLine(&quot;Deus Ex&quot; + &quot;2&quot;);\n    sb.AppendLine(&quot;System Shock&quot;);\n    Console.WriteLine(sb.ToString());\n    sb.Replace(&quot;2&quot;, &quot; Invisible War&quot;);\n    Console.WriteLine(sb.ToString());\n    Console.WriteLine(&quot;sb has {0} chars.&quot;, sb.Length);\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>Here, I have constructed a StringBuilder set to the initial value &quot;<strong><strong> Fantastic Games  <\/strong><\/strong>&quot;.  As you can see, I am appending to the internal buffer and am able to replace or remove characters at will. By default, a StringBuilder is only able to initially hold a string of 16 characters or fewer (but will expand automatically if necessary); however, this default starting value can be changed via an additional constructor argument. \u5728\u8fd9\u91cc\uff0c\u6211\u6784\u9020\u4e86\u4e00\u4e2a\u8bbe\u7f6e\u4e3a\u521d\u59cb\u503c\u201c<strong><strong> Fantastic Games <\/strong><\/strong>\u201d\u7684 StringBuilder\u3002<br \/>\n\u5982\u60a8\u6240\u89c1\uff0c\u6211\u6b63\u5728\u8ffd\u52a0\u5230\u5185\u90e8\u7f13\u51b2\u533a\uff0c\u5e76\u4e14\u80fd\u591f\u968f\u610f\u66ff\u6362\u6216\u5220\u9664\u5b57\u7b26\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cStringBuilder \u6700\u521d\u53ea\u80fd\u5bb9\u7eb3 16 \u4e2a\u5b57\u7b26\u6216\u66f4\u5c11\u7684\u5b57\u7b26\u4e32\uff08\u4f46\u5982\u6709\u5fc5\u8981\u4f1a\u81ea\u52a8\u6269\u5c55\uff09;\u4f46\u662f\uff0c\u53ef\u4ee5\u901a\u8fc7\u5176\u4ed6\u6784\u9020\u51fd\u6570\u53c2\u6570\u66f4\u6539\u6b64\u9ed8\u8ba4\u8d77\u59cb\u503c\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \n\/\/ Make a StringBuilder with an initial size of 256. \n\/\/ \u521b\u5efa\u4e00\u4e2a\u521d\u59cb\u5927\u5c0f\u4e3a 256 \u7684 StringBuilder\u3002\nStringBuilder sb = new StringBuilder(&quot;**** Fantastic Games ****&quot;, 256);\n<\/pre>\n<\/p>\n<p>If you append more characters than the specified limit, the StringBuilder object will copy its data into a new instance and grow the buffer by the specified limit.<br \/>\n\u5982\u679c\u8ffd\u52a0\u7684\u5b57\u7b26\u6570\u8d85\u8fc7\u6307\u5b9a\u7684\u9650\u5236\uff0c\u5219 StringBuilder \u5bf9\u8c61\u4f1a\u5c06\u5176\u6570\u636e\u590d\u5236\u5230\u65b0\u5b9e\u4f8b\u4e2d\uff0c\u5e76\u6309\u6307\u5b9a\u7684\u9650\u5236\u589e\u52a0\u7f13\u51b2\u533a\u3002<\/p>\n<h2>Narrowing and Widening Data Type Conversions<\/h2>\n<p>\u7f29\u5c0f\u548c\u6269\u5927\u6570\u636e\u7c7b\u578b\u8f6c\u6362<\/p>\n<p>Now that you understand how to work with intrinsic C# data types, let\u2019s examine the related topic of data type conversion. Assume you have a new Console Application project named TypeConversions and added it to your solution. Update the code to match the following:<br \/>\n\u73b0\u5728\uff0c\u4f60\u5df2\u4e86\u89e3\u5982\u4f55\u4f7f\u7528\u5185\u90e8 C# \u6570\u636e\u7c7b\u578b\uff0c\u63a5\u4e0b\u6765\u8ba9\u6211\u4eec\u6765\u770b\u770b\u6570\u636e\u7c7b\u578b\u8f6c\u6362\u7684\u76f8\u5173\u4e3b\u9898\u3002\u5047\u8bbe\u60a8\u6709\u4e00\u4e2a\u540d\u4e3a TypeConversions \u7684\u65b0\u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u9879\u76ee\uff0c\u5e76\u5c06\u5176\u6dfb\u52a0\u5230\u60a8\u7684\u89e3\u51b3\u65b9\u6848\u4e2d\u3002\u66f4\u65b0\u4ee3\u7801\u4ee5\u5339\u914d\u4ee5\u4e0b\u5185\u5bb9\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nConsole.WriteLine(&quot;***** Fun with type conversions *****&quot;);\n\/\/ Add two shorts and print the result.\n\/\/ \u6dfb\u52a0\u4e24\u4e2ashorts \u7c7b\u578b\u6570\u636e\u5e76\u6253\u5370\u7ed3\u679c\u3002\nshort numb1 = 9, numb2 = 10;\nConsole.WriteLine(&quot;{0} + {1} = {2}&quot;,\nnumb1, numb2, Add(numb1, numb2));\nConsole.ReadLine();\nstatic int Add(int x, int y)\n{\n    return x + y;\n}\n<\/pre>\n<\/p>\n<p>Notice that the Add() method expects to be sent two int parameters. However, the calling code is, in fact, sending in two short variables. While this might seem like a complete and total mismatch of data types, the program compiles and executes without error, returning the expected result of 19.<br \/>\n\u8bf7\u6ce8\u610f\uff0cAdd\uff08\uff09 \u65b9\u6cd5\u671f\u671b\u53d1\u9001\u4e24\u4e2a int \u53c2\u6570\u3002\u4f46\u662f\uff0c\u8c03\u7528\u4ee3\u7801\u5b9e\u9645\u4e0a\u53d1\u9001\u4e86\u4e24\u4e2a\u77ed\u53d8\u91cf\u3002\u867d\u7136\u8fd9\u770b\u8d77\u6765\u50cf\u662f\u6570\u636e\u7c7b\u578b\u7684\u5b8c\u5168\u4e0d\u5339\u914d\uff0c\u4f46\u7a0b\u5e8f\u7f16\u8bd1\u548c\u6267\u884c\u65f6\u6ca1\u6709\u9519\u8bef\uff0c\u8fd4\u56de\u9884\u671f\u7ed3\u679c 19\u3002<\/p>\n<p>The reason the compiler treats this code as syntactically sound is because there is no possibility for loss of data. Given that the maximum value of a short (32,767) is well within the maximum range of an int (2,147,483,647), the compiler implicitly widens each short to an int. Formally speaking, widening is the term used to define an implicit upward cast that does not result in a loss of data.<br \/>\n\u7f16\u8bd1\u5668\u5c06\u6b64\u4ee3\u7801\u89c6\u4e3a\u8bed\u6cd5\u5408\u7406\u7684\u539f\u56e0\u662f\u6ca1\u6709\u6570\u636e\u4e22\u5931\u7684\u53ef\u80fd\u6027\u3002\u9274\u4e8e short \u7684\u6700\u5927\u503c \uff0832,767\uff09 \u5b8c\u5168\u5728 int \uff082,147,483,647\uff09 \u7684\u6700\u5927\u8303\u56f4\u5185\uff0c\u7f16\u8bd1\u5668\u4f1a\u5c06\u6bcf\u4e2a short \u9690\u5f0f\u6269\u5927\u5230 int\u3002\u4ece\u5f62\u5f0f\u4e0a\u8bb2\uff0c\u52a0\u5bbd\u662f\u7528\u4e8e\u5b9a\u4e49\u4e0d\u4f1a\u5bfc\u81f4\u6570\u636e\u4e22\u5931\u7684\u9690\u5f0f\u5411\u4e0a\u8f6c\u6362\u7684\u672f\u8bed\u3002<\/p>\n<blockquote><p>\n\u25a0 Note  Look up \u201ctype Conversion tables\u201d in the .net Core documentation if you want to see permissible widening (and narrowing, discussed next) conversions for each C# data type.<br \/>\n\u6ce8\u610f \u5982\u679c\u8981\u67e5\u770b\u6bcf\u79cd C# \u6570\u636e\u7c7b\u578b\u7684\u5141\u8bb8\u52a0\u5bbd\uff08\u548c\u7f29\u5c0f\uff0c\u4e0b\u6587\u5c06\u8ba8\u8bba\uff09\u8f6c\u6362\uff0c\u8bf7\u5728 .net Core \u6587\u6863\u4e2d\u67e5\u627e\u201c\u7c7b\u578b\u8f6c\u6362\u8868\u201d\u3002\n<\/p><\/blockquote>\n<p>Although this implicit widening worked in your favor for the previous example, other times this \u201cfeature\u201d can be the source of compile-time errors. For example, assume you have set values to numb1 and numb2 that (when added together) overflow the maximum value of a short. Also, assume you are storing the return value of the Add() method within a new local short variable, rather than directly printing the result to the console.<br \/>\n\u5c3d\u7ba1\u8fd9\u79cd\u9690\u5f0f\u52a0\u5bbd\u5728\u524d\u9762\u7684\u793a\u4f8b\u4e2d\u5bf9\u60a8\u6709\u5229\uff0c\u4f46\u5176\u4ed6\u65f6\u5019\u6b64\u201c\u529f\u80fd\u201d\u53ef\u80fd\u662f\u7f16\u8bd1\u65f6\u9519\u8bef\u7684\u6839\u6e90\u3002\u4f8b\u5982\uff0c\u5047\u8bbe\u60a8\u5df2\u5c06\u503c\u8bbe\u7f6e\u4e3a numb1 \u548c numb2\uff0c\u8fd9\u4e9b\u503c\uff08\u52a0\u5728\u4e00\u8d77\u65f6\uff09\u4f1a\u6ea2\u51fa\u77ed\u7ebf\u7684\u6700\u5927\u503c\u3002 \u6b64\u5916\uff0c\u5047\u8bbe\u60a8\u5c06 Add\uff08\uff09 \u65b9\u6cd5\u7684\u8fd4\u56de\u503c\u5b58\u50a8\u5728\u65b0\u7684\u5c40\u90e8\u77ed\u53d8\u91cf\u4e2d\uff0c\u800c\u4e0d\u662f\u76f4\u63a5\u5c06\u7ed3\u679c\u6253\u5370\u5230\u63a7\u5236\u53f0\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nConsole.WriteLine(&quot;***** Fun with type conversions *****&quot;);\n\/\/ Compiler error below!\n\/\/ \u4e0b\u9762\u7684\u7f16\u8bd1\u5668\u9519\u8bef\uff01\nshort numb1 = 30000, numb2 = 30000;\nshort answer = Add(numb1, numb2);\nConsole.WriteLine(&quot;{0} + {1} = {2}&quot;,\nnumb1, numb2, answer);\nConsole.ReadLine();\n<\/pre>\n<\/p>\n<p>In this case, the compiler reports the following error:<br \/>\n\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u7f16\u8bd1\u5668\u5c06\u62a5\u544a\u4ee5\u4e0b\u9519\u8bef\uff1a<\/p>\n<blockquote><p>\nCannot implicitly convert type 'int' to 'short'. An explicit conversion exists (are you missing a cast?)<br \/>\n\u4e0d\u80fd\u5c06\u7c7b\u578b\u201cint\u201d\u9690\u5f0f\u8f6c\u6362\u4e3a\u201cshort\u201d\u3002\u5b58\u5728\u663e\u5f0f\u8f6c\u6362\uff08\u60a8\u662f\u5426\u7f3a\u5c11\u5f3a\u5236\u8f6c\u6362\uff1f\n<\/p><\/blockquote>\n<p>The problem is that although the Add() method is capable of returning an int with the value 60,000 (which fits within the range of a System.Int32), the value cannot be stored in a short, as it overflows the bounds of this data type. Formally speaking, the CoreCLR was unable to apply a narrowing operation. As you can guess, narrowing is the logical opposite of widening, in that a larger value is stored within a smaller data type variable.<br \/>\n\u95ee\u9898\u5728\u4e8e\uff0c\u5c3d\u7ba1 Add\uff08\uff09 \u65b9\u6cd5\u80fd\u591f\u8fd4\u56de\u503c\u4e3a 60,000 \u7684 int\uff08\u8fd9\u7b26\u5408 System.Int32 \u7684\u8303\u56f4\uff09\uff0c\u4f46\u8be5\u503c\u4e0d\u80fd\u5b58\u50a8\u5728\u77ed\u65f6\u95f4\u5185\uff0c\u56e0\u4e3a\u5b83\u4f1a\u6ea2\u51fa\u6b64\u6570\u636e\u7c7b\u578b\u7684\u8fb9\u754c\u3002\u4ece\u5f62\u5f0f\u4e0a\u8bb2\uff0cCoreCLR\u65e0\u6cd5\u5e94\u7528\u7f29\u5c0f\u64cd\u4f5c\u3002\u60a8\u53ef\u4ee5\u731c\u5230\uff0c\u7f29\u5c0f\u5728\u903b\u8f91\u4e0a\u4e0e\u52a0\u5bbd\u76f8\u53cd\uff0c\u56e0\u4e3a\u8f83\u5927\u7684\u503c\u5b58\u50a8\u5728\u8f83\u5c0f\u7684\u6570\u636e\u7c7b\u578b\u53d8\u91cf\u4e2d\u3002<\/p>\n<p>It is important to point out that all narrowing conversions result in a compiler error, even when you can reason that the narrowing conversion should indeed succeed. For example, the following code also results in a compiler error:<br \/>\n\u8bf7\u52a1\u5fc5\u6307\u51fa\uff0c\u6240\u6709\u7f29\u5c0f\u8f6c\u6362\u90fd\u4f1a\u5bfc\u81f4\u7f16\u8bd1\u5668\u9519\u8bef\uff0c\u5373\u4f7f\u60a8\u53ef\u4ee5\u63a8\u65ad\u7f29\u5c0f\u8f6c\u6362\u786e\u5b9e\u5e94\u8be5\u6210\u529f\u3002\u4f8b\u5982\uff0c\u4ee5\u4e0b\u4ee3\u7801\u8fd8\u4f1a\u5bfc\u81f4\u7f16\u8bd1\u5668\u9519\u8bef\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Another compiler error!\n\/\/ \u53e6\u4e00\u4e2a\u7f16\u8bd1\u5668\u9519\u8bef\uff01\nstatic void NarrowingAttempt()\n{\n    byte myByte = 0;\n    int myInt = 200;\n    myByte = myInt;\n    Console.WriteLine(&quot;Value of myByte: {0}&quot;, myByte);\n}\n<\/pre>\n<\/p>\n<p>Here, the value contained within the int variable (myInt) is safely within the range of a byte; therefore, you would expect the narrowing operation to not result in a runtime error. However, given that C# is a language built with type safety in mind, you do indeed receive a compiler error.<br \/>\n\u5728\u8fd9\u91cc\uff0cint \u53d8\u91cf \uff08myInt\uff09 \u4e2d\u5305\u542b\u7684\u503c\u5b89\u5168\u5730\u5728\u4e00\u4e2a\u5b57\u8282\u7684\u8303\u56f4\u5185;\u56e0\u6b64\uff0c\u60a8\u5e0c\u671b\u7f29\u5c0f\u64cd\u4f5c\u4e0d\u4f1a\u5bfc\u81f4\u8fd0\u884c\u65f6\u9519\u8bef\u3002\u4f46\u662f\uff0c\u9274\u4e8e C# \u662f\u4e00\u79cd\u5728\u6784\u5efa\u65f6\u8003\u8651\u4e86\u7c7b\u578b\u5b89\u5168\u7684\u8bed\u8a00\uff0c\u60a8\u786e\u5b9e\u4f1a\u6536\u5230\u7f16\u8bd1\u5668\u9519\u8bef\u3002<\/p>\n<p>When you want to inform the compiler that you are willing to deal with a possible loss of data because of a narrowing operation, you must apply an explicit cast using the C# casting operator, (). Consider the following update to the Program.cs file:<br \/>\n\u5982\u679c\u8981\u901a\u77e5\u7f16\u8bd1\u5668\u60a8\u613f\u610f\u5904\u7406\u7531\u4e8e\u7f29\u5c0f\u64cd\u4f5c\u800c\u53ef\u80fd\u4e22\u5931\u7684\u6570\u636e\uff0c\u5219\u5fc5\u987b\u4f7f\u7528 C# \u5f3a\u5236\u8f6c\u6362\u8fd0\u7b97\u7b26 \uff08\uff09 \u5e94\u7528\u663e\u5f0f\u5f3a\u5236\u8f6c\u6362\u3002\u8bf7\u8003\u8651\u5bf9 Program.cs \u6587\u4ef6\u8fdb\u884c\u4ee5\u4e0b\u66f4\u65b0\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nConsole.WriteLine(&quot;***** Fun with type conversions *****&quot;);\nshort numb1 = 30000, numb2 = 30000;\n\n\/\/ Explicitly cast the int into a short (and allow loss of data).\n\/\/ \u5c06 int \u663e\u5f0f\u8f6c\u6362\u4e3a\u77ed\u6574\u578b\uff08\u5e76\u5141\u8bb8\u4e22\u5931\u6570\u636e\uff09\u3002\nshort answer = (short)Add(numb1, numb2);\nConsole.WriteLine(&quot;{0} + {1} = {2}&quot;,\nnumb1, numb2, answer);\nNarrowingAttempt();\nConsole.ReadLine();\nstatic int Add(int x, int y)\n{\n    return x + y;\n}\nstatic void NarrowingAttempt()\n{\n    byte myByte = 0;\n    int myInt = 200;\n    \/\/ Explicitly cast the int into a byte (no loss of data).\n    \/\/ \u5c06 int \u663e\u5f0f\u8f6c\u6362\u4e3a\u5b57\u8282\uff08\u4e0d\u4e22\u5931\u6570\u636e\uff09\u3002\n    myByte = (byte)myInt;\n    Console.WriteLine(&quot;Value of myByte: {0}&quot;, myByte);\n}\n<\/pre>\n<\/p>\n<p>At this point, the code compiles; however, the result of the addition is completely incorrect.<br \/>\n\u6b64\u65f6\uff0c\u4ee3\u7801\u5c06\u7f16\u8bd1;\u4f46\u662f\uff0c\u6dfb\u52a0\u7684\u7ed3\u679c\u662f\u5b8c\u5168\u4e0d\u6b63\u786e\u7684\u3002<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n***** Fun with type conversions ***** \n30000 + 30000 = -5536\nValue of myByte: 200\n<\/pre>\n<\/p>\n<p>As you have just witnessed, an explicit cast allows you to force the compiler to apply a narrowing conversion, even when doing so may result in a loss of data. In the case of the NarrowingAttempt() method, this was not a problem because the value 200 can fit snugly within the range of a byte. However, in the case of adding the two shorts within the code, the end result is completely unacceptable (30,000 + 30,000 =\u20135536?).<br \/>\n\u6b63\u5982\u60a8\u521a\u624d\u6240\u76ee\u7779\u7684\uff0c\u663e\u5f0f\u5f3a\u5236\u8f6c\u6362\u5141\u8bb8\u60a8\u5f3a\u5236\u7f16\u8bd1\u5668\u5e94\u7528\u7f29\u5c0f\u8f6c\u6362\uff0c\u5373\u4f7f\u8fd9\u6837\u505a\u53ef\u80fd\u4f1a\u5bfc\u81f4\u6570\u636e\u4e22\u5931\u3002\u5728 NarrowingTry\uff08\uff09 \u65b9\u6cd5\u7684\u60c5\u51b5\u4e0b\uff0c\u8fd9\u4e0d\u662f\u95ee\u9898\uff0c\u56e0\u4e3a\u503c 200 \u53ef\u4ee5\u7d27\u8d34\u5728\u5b57\u8282\u7684\u8303\u56f4\u5185\u3002\u4f46\u662f\uff0c\u5728\u4ee3\u7801\u4e2d\u6dfb\u52a0\u4e24\u4e2a\u77eds \u7684\u60c5\u51b5\u4e0b\uff0c\u6700\u7ec8\u7ed3\u679c\u662f\u5b8c\u5168\u4e0d\u53ef\u63a5\u53d7\u7684\uff0830,000 + 30,000 =\u20135536?).<\/p>\n<p>If you are building an application where loss of data is always unacceptable, C# provides the checked and unchecked keywords to ensure data loss does not escape undetected.<br \/>\n\u5982\u679c\u6b63\u5728\u6784\u5efa\u7684\u5e94\u7528\u7a0b\u5e8f\u59cb\u7ec8\u65e0\u6cd5\u63a5\u53d7\u6570\u636e\u4e22\u5931\uff0cC# \u5c06\u63d0\u4f9b\u5df2\u68c0\u67e5\u7684\u548c\u672a\u9009\u4e2d\u7684\u5173\u952e\u5b57\uff0c\u4ee5\u786e\u4fdd\u6570\u636e\u4e22\u5931\u4e0d\u4f1a\u9003\u8131\u800c\u672a\u88ab\u53d1\u73b0\u3002<\/p>\n<h2>Using the checked Keyword<\/h2>\n<p>\u4f7f\u7528\u9009\u4e2d\u7684\u5173\u952e\u5b57<\/p>\n<p>Let\u2019s begin by learning the role of the checked keyword. Assume you have a new method within Program that attempts to add two bytes, each of which has been assigned a value that is safely below the maximum (255). If you were to add the values of these types (casting the returned int to a byte), you would assume that the result would be the exact sum of each member.<br \/>\n\u8ba9\u6211\u4eec\u4ece\u5b66\u4e60\u9009\u4e2d\u5173\u952e\u5b57\u7684\u4f5c\u7528\u5f00\u59cb\u3002\u5047\u8bbe\u60a8\u5728\u7a0b\u5e8f\u4e2d\u6709\u4e00\u4e2a\u65b0\u65b9\u6cd5\uff0c\u8be5\u65b9\u6cd5\u5c1d\u8bd5\u6dfb\u52a0\u4e24\u4e2a\u5b57\u8282\uff0c\u6bcf\u4e2a\u5b57\u8282\u90fd\u5206\u914d\u4e86\u4e00\u4e2a\u5b89\u5168\u4f4e\u4e8e\u6700\u5927\u503c \uff08255\uff09 \u7684\u503c\u3002\u5982\u679c\u8981\u6dfb\u52a0\u8fd9\u4e9b\u7c7b\u578b\u7684\u503c\uff08\u5c06\u8fd4\u56de\u7684 int \u5f3a\u5236\u8f6c\u6362\u4e3a\u5b57\u8282\uff09\uff0c\u5219\u5047\u5b9a\u7ed3\u679c\u5c06\u662f\u6bcf\u4e2a\u6210\u5458\u7684\u786e\u5207\u603b\u548c\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void ProcessBytes()\n{\n    byte b1 = 100;\n    byte b2 = 250;\n    byte sum = (byte)Add(b1, b2);\n    \/\/ sum should hold the value 350. However, we find the value 94!\n    \/\/ \u603b\u548c\u5e94\u4fdd\u6301\u503c 350\u3002\u4f46\u662f\uff0c\u6211\u4eec\u53d1\u73b0\u503c\u4e3a 94\uff01\n    Console.WriteLine(&quot;sum = {0}&quot;, sum);\n}\n<\/pre>\n<\/p>\n<p>If you were to view the output of this application, you might be surprised to find that sum contains the value 94 (rather than the expected 350). The reason is simple. Given that a System.Byte can hold a value only between 0 and 255 (inclusive, for a grand total of 256 slots), sum now contains the overflow value (350 \u2013 256 = 94). By default, if you take no corrective course of action, overflow\/underflow conditions occur without error.<br \/>\n\u5982\u679c\u8981\u67e5\u770b\u6b64\u5e94\u7528\u7a0b\u5e8f\u7684\u8f93\u51fa\uff0c\u60a8\u53ef\u80fd\u4f1a\u60ca\u8bb6\u5730\u53d1\u73b0 sum \u5305\u542b\u503c 94\uff08\u800c\u4e0d\u662f\u9884\u671f\u7684 350\uff09\u3002\u539f\u56e0\u5f88\u7b80\u5355\u3002\u5047\u8bbe System.Byte \u53ea\u80fd\u4fdd\u5b58\u4ecb\u4e8e 0 \u548c 255 \u4e4b\u95f4\u7684\u503c\uff08\u5305\u62ec 256 \u5230 &lt;&gt; \u4e2a\u63d2\u69fd\uff09\uff0c\u5219 sum \u73b0\u5728\u5305\u542b\u6ea2\u51fa\u503c\uff08350 \u2013 256 = 94\uff09\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u5982\u679c\u4e0d\u91c7\u53d6\u7ea0\u6b63\u63aa\u65bd\uff0c\u5219\u4f1a\u53d1\u751f\u6ea2\u51fa\/\u4e0b\u6ea2\u60c5\u51b5\u800c\u4e0d\u4f1a\u51fa\u9519\u3002<\/p>\n<p>To handle overflow or underflow conditions in your application, you have two options. Your first choice is to leverage your wits and programming skills to handle all overflow\/underflow conditions manually. Of course, the problem with this technique is the simple fact that you are human, and even your best attempts might result in errors that have escaped your eyes.<br \/>\n\u8981\u5904\u7406\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u6ea2\u51fa\u6216\u4e0b\u6ea2\u60c5\u51b5\uff0c\u60a8\u6709\u4e24\u4e2a\u9009\u9879\u3002\u60a8\u7684\u9996\u9009\u662f\u5229\u7528\u60a8\u7684\u667a\u6167\u548c\u7f16\u7a0b\u6280\u80fd\u624b\u52a8\u5904\u7406\u6240\u6709\u6ea2\u51fa\/\u4e0b\u6ea2\u60c5\u51b5\u3002\u5f53\u7136\uff0c\u8fd9\u79cd\u6280\u672f\u7684\u95ee\u9898\u5728\u4e8e\u4f60\u662f\u4eba\u7c7b\u7684\u7b80\u5355\u4e8b\u5b9e\uff0c\u5373\u4f7f\u662f\u4f60\u6700\u597d\u7684\u5c1d\u8bd5\u4e5f\u53ef\u80fd\u5bfc\u81f4\u4f60\u773c\u775b\u4e4b\u5916\u7684\u9519\u8bef\u3002<\/p>\n<p>Thankfully, C# provides the checked keyword. When you wrap a statement (or a block of statements) within the scope of the checked keyword, the C# compiler emits additional CIL instructions that test for overflow conditions that may result when adding, multiplying, subtracting, or dividing two numerical data types.<br \/>\n\u503c\u5f97\u5e86\u5e78\u7684\u662f\uff0cC# \u63d0\u4f9b\u4e86 checked \u5173\u952e\u5b57\u3002\u5c06\u8bed\u53e5\uff08\u6216\u8bed\u53e5\u5757\uff09\u5305\u88c5\u5728 checked \u5173\u952e\u5b57\u7684\u8303\u56f4\u5185\u65f6\uff0cC# \u7f16\u8bd1\u5668\u4f1a\u53d1\u51fa\u5176\u4ed6 CIL \u6307\u4ee4\uff0c\u7528\u4e8e\u6d4b\u8bd5\u5728\u6dfb\u52a0\u3001\u4e58\u6cd5\u3001\u51cf\u53bb\u6216\u9664\u4ee5\u4e24\u79cd\u6570\u503c\u6570\u636e\u7c7b\u578b\u65f6\u53ef\u80fd\u5bfc\u81f4\u7684\u6ea2\u51fa\u60c5\u51b5\u3002<\/p>\n<p>If an overflow has occurred, you will receive a runtime exception: System.OverflowException.Chapter 7 will examine all the details of structured exception handling and the use of the try and catch keywords. Without getting too hung up on the specifics at this point, observe the following update:<br \/>\n\u5982\u679c\u53d1\u751f\u6ea2\u51fa\uff0c\u60a8\u5c06\u6536\u5230\u8fd0\u884c\u65f6\u5f02\u5e38\uff1aSystem.OverflowException\u3002\u7b2c7\u7ae0\u5c06\u7814\u7a76\u7ed3\u6784\u5316\u5f02\u5e38\u5904\u7406\u7684\u6240\u6709\u7ec6\u8282\u4ee5\u53catry\u548ccatch\u7684\u4f7f\u7528\u3002\u5173\u952e\u5b57\u3002\u5728\u8fd9\u4e00\u70b9\u4e0a\uff0c\u4e0d\u8981\u592a\u7ea0\u7ed3\u4e8e\u7ec6\u8282\uff0c\u8bf7\u89c2\u5bdf\u4ee5\u4e0b\u66f4\u65b0\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void ProcessBytes()\n{\n    byte b1 = 100;\n    byte b2 = 250;\n    \/\/ This time, tell the compiler to add CIL code\n    \/\/ \u8fd9\u4e00\u6b21\uff0c\u544a\u8bc9\u7f16\u8bd1\u5668\u6dfb\u52a0 CIL \u4ee3\u7801\n    \/\/ to throw an exception if overflow\/underflow\n    \/\/ \u5728\u6ea2\u51fa\/\u4e0b\u6ea2\u65f6\u5f15\u53d1\u5f02\u5e38\n    \/\/ takes place.\u53d1\u751f\u3002\n    try\n    {\n        byte sum = checked((byte)Add(b1, b2));\n        Console.WriteLine(&quot;sum = {0}&quot;, sum);\n    }\n    catch (OverflowException ex)\n    {\n        Console.WriteLine(ex.Message);\n    }\n}\n<\/pre>\n<\/p>\n<p>Notice that the return value of Add() has been wrapped within the scope of the checked keyword.Because the sum is greater than a byte, this triggers a runtime exception. Notice the error message printed out via the Message property.<br \/>\n\u8bf7\u6ce8\u610f\uff0cAdd\uff08\uff09 \u7684\u8fd4\u56de\u503c\u5df2\u5305\u88c5\u5728 checked \u5173\u952e\u5b57\u7684\u8303\u56f4\u5185\u3002\u7531\u4e8e\u603b\u548c\u5927\u4e8e\u4e00\u4e2a\u5b57\u8282\uff0c\u56e0\u6b64\u4f1a\u89e6\u53d1\u8fd0\u884c\u65f6\u5f02\u5e38\u3002\u8bf7\u6ce8\u610f\u901a\u8fc7 Message \u5c5e\u6027\u6253\u5370\u51fa\u7684\u9519\u8bef\u6d88\u606f\u3002<\/p>\n<p><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nArithmetic operation resulted in an overflow. \n\u7b97\u672f\u8fd0\u7b97\u5bfc\u81f4\u6ea2\u51fa\u3002\n<\/pre>\n<\/p>\n<p>If you want to force overflow checking to occur over a block of code statements, you can do so by defining a \u201cchecked scope\u201d as follows:<br \/>\n\u5982\u679c\u8981\u5f3a\u5236\u5bf9\u4ee3\u7801\u8bed\u53e5\u5757\u8fdb\u884c\u6ea2\u51fa\u68c0\u67e5\uff0c\u53ef\u4ee5\u901a\u8fc7\u5b9a\u4e49\u201c\u5df2\u68c0\u67e5\u8303\u56f4\u201d\u6765\u5b9e\u73b0\uff0c\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\ntry\n{\n    checked\n    {\n        byte sum = (byte)Add(b1, b2);\n        Console.WriteLine(&quot;sum = {0}&quot;, sum);\n    }\n}\ncatch (OverflowException ex)\n{\n    Console.WriteLine(ex.Message);\n}\n<\/pre>\n<\/p>\n<p>In either case, the code in question will be evaluated for possible overflow conditions automatically, which will trigger an overflow exception if encountered.<br \/>\n\u65e0\u8bba\u54ea\u79cd\u60c5\u51b5\uff0c\u90fd\u4f1a\u81ea\u52a8\u8bc4\u4f30\u76f8\u5173\u4ee3\u7801\u662f\u5426\u5b58\u5728\u53ef\u80fd\u7684\u6ea2\u51fa\u60c5\u51b5\uff0c\u5982\u679c\u9047\u5230\u6ea2\u51fa\u60c5\u51b5\uff0c\u8fd9\u5c06\u89e6\u53d1\u6ea2\u51fa\u5f02\u5e38\u3002<\/p>\n<h2>Setting Project-wide Overflow Checking (Project File)<\/h2>\n<p>\u8bbe\u7f6e\u9879\u76ee\u8303\u56f4\u7684\u6ea2\u51fa\u68c0\u67e5\uff08\u9879\u76ee\u6587\u4ef6\uff09<\/p>\n<p>If you are creating an application that should never allow silent overflow to occur, you might find yourself in the annoying position of wrapping numerous lines of code within the scope of the checked keyword. As an alternative, the C# compiler supports the \/checked flag. When it\u2019s enabled, all your arithmetic will be evaluated for overflow without the need to make use of the C# checked keyword. If overflow has been discovered, you will still receive a runtime exception. To set this for the entire project, enter the following into the project file:<br \/>\n\u5982\u679c\u60a8\u6b63\u5728\u521b\u5efa\u4e00\u4e2a\u6c38\u8fdc\u4e0d\u5141\u8bb8\u53d1\u751f\u9759\u9ed8\u6ea2\u51fa\u7684\u5e94\u7528\u7a0b\u5e8f\uff0c\u60a8\u53ef\u80fd\u4f1a\u53d1\u73b0\u81ea\u5df1\u5904\u4e8e\u5728 checked \u5173\u952e\u5b57\u8303\u56f4\u5185\u5305\u88c5\u5927\u91cf\u4ee3\u7801\u7684\u70e6\u4eba\u4f4d\u7f6e\u3002\u4f5c\u4e3a\u66ff\u4ee3\u65b9\u6cd5\uff0cC# \u7f16\u8bd1\u5668\u652f\u6301 \/checked \u6807\u5fd7\u3002\u542f\u7528\u540e\uff0c\u5c06\u8ba1\u7b97\u6240\u6709\u7b97\u672f\u662f\u5426\u6ea2\u51fa\uff0c\u800c\u65e0\u9700\u4f7f\u7528 C# checked \u5173\u952e\u5b57\u3002\u5982\u679c\u53d1\u73b0\u6ea2\u51fa\uff0c\u60a8\u4ecd\u5c06\u6536\u5230\u8fd0\u884c\u65f6\u5f02\u5e38\u3002\u8981\u4e3a\u6574\u4e2a\u9879\u76ee\u8bbe\u7f6e\u6b64\u9879\uff0c\u8bf7\u5728\u9879\u76ee\u6587\u4ef6\u4e2d\u8f93\u5165\u4ee5\u4e0b\u5185\u5bb9\uff1a<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;PropertyGroup&gt;\n    &lt;CheckForOverflowUnderflow&gt;true&lt;\/CheckForOverflowUnderflow&gt;\n&lt;\/PropertyGroup&gt;\n<\/pre>\n<\/p>\n<h2>Setting Project-wide Overflow Checking (Visual Studio)<\/h2>\n<p>\u8bbe\u7f6e\u9879\u76ee\u8303\u56f4\u7684\u6ea2\u51fa\u68c0\u67e5\uff08Visual Studio\uff09<\/p>\n<p>To enable the \u201cCheck for arithmetic overflow\u201d flag, open the project\u2019s property page. Note that Visual Studio 2022 has updated the project settings dialog pretty significantly from Visual Studio 2019. Most of the options in the dialog now have a descriptor along with the setting. Select General from the Build menu (on the left side of the dialog) and then select the \u201cCheck for arithmetic overflow\/underflow\u201d check box (see Figure 3-3). Enabling this setting can be helpful when you are creating a debug build. After all the overflow exceptions have been squashed out of the code base, you are free to disable the \/checked flag for subsequent builds (which can increase the runtime performance of your application).<br \/>\n\u82e5\u8981\u542f\u7528\u201c\u68c0\u67e5\u7b97\u672f\u6ea2\u51fa\u201d\u6807\u5fd7\uff0c\u8bf7\u6253\u5f00\u9879\u76ee\u7684\u5c5e\u6027\u9875\u3002\u8bf7\u6ce8\u610f\uff0cVisual Studio 2022 \u5df2\u4ece Visual Studio 2019 \u4e2d\u663e\u7740\u66f4\u65b0\u4e86\u9879\u76ee\u8bbe\u7f6e\u5bf9\u8bdd\u6846\u3002\u5bf9\u8bdd\u6846\u4e2d\u7684\u5927\u591a\u6570\u9009\u9879\u73b0\u5728\u90fd\u6709\u4e00\u4e2a\u63cf\u8ff0\u7b26\u548c\u8bbe\u7f6e\u3002\u4ece\u201c\u751f\u6210\u201d\u83dc\u5355\uff08\u4f4d\u4e8e\u5bf9\u8bdd\u6846\u5de6\u4fa7\uff09\u4e2d\u9009\u62e9\u201c\u5e38\u89c4\u201d\uff0c\u7136\u540e\u9009\u4e2d\u201c\u68c0\u67e5\u7b97\u672f\u6ea2\u51fa\/\u4e0b\u6ea2\u201d\u590d\u9009\u6846\uff08\u8bf7\u53c2\u9605\u56fe 3-3\uff09\u3002\u5728\u521b\u5efa\u8c03\u8bd5\u7248\u672c\u65f6\uff0c\u542f\u7528\u6b64\u8bbe\u7f6e\u4f1a\u5f88\u6709\u5e2e\u52a9\u3002\u4ece\u4ee3\u7801\u5e93\u4e2d\u6e05\u9664\u6240\u6709\u6ea2\u51fa\u5f02\u5e38\u540e\uff0c\u60a8\u53ef\u4ee5\u81ea\u7531\u5730\u7981\u7528\u540e\u7eed\u6784\u5efa\u7684 \/checked \u6807\u5fd7\uff08\u8fd9\u53ef\u4ee5\u63d0\u9ad8\u5e94\u7528\u7a0b\u5e8f\u7684\u8fd0\u884c\u65f6\u6027\u80fd\uff09\u3002<\/p>\n<blockquote><p>\n\u25a0 Note the configuration selection is updated in Visual studio 2022. the gear icon shows up only when you hover your mouse pointer by the check box or to the left of the title. selecting the configuration is covered next.<br \/>\n\u8bf7\u6ce8\u610f\uff0c\u914d\u7f6e\u9009\u62e9\u5728 Visual Studio 2022 \u4e2d\u66f4\u65b0\u3002 \u4ec5\u5f53\u60a8\u5c06\u9f20\u6807\u6307\u9488\u60ac\u505c\u5728\u590d\u9009\u6846\u4e0a\u6216\u6807\u9898\u5de6\u4fa7\u65f6\uff0c\u9f7f\u8f6e\u56fe\u6807\u624d\u4f1a\u663e\u793a\u3002 \u63a5\u4e0b\u6765\u5c06\u4ecb\u7ecd\u5982\u4f55\u9009\u62e9\u914d\u7f6e\u3002\n<\/p><\/blockquote>\n<p><img decoding=\"async\" src=\"https:\/\/miie.net\/img\/pro-csharp10\/images\/0303.png\" alt=\"Alt text\" \/><\/p>\n<p>Figure 3-3. Enabling project-wide overflow\/underflow data checking<br \/>\n\u56fe 3-3\u3002 \u542f\u7528\u9879\u76ee\u8303\u56f4\u7684\u6ea2\u51fa\/\u4e0b\u6ea2\u6570\u636e\u68c0\u67e5<\/p>\n<h2>Selecting the Build Configuration<\/h2>\n<p>\u9009\u62e9\u6784\u5efa\u914d\u7f6e<\/p>\n<p>To select all configurations or a specific configuration for a build option, hover with your mouse over the check box or to the left of the title. Click the gear that appears, and you will see the build configuration selector shown in Figure 3-4.<br \/>\n\u82e5\u8981\u4e3a\u751f\u6210\u9009\u9879\u9009\u62e9\u6240\u6709\u914d\u7f6e\u6216\u7279\u5b9a\u914d\u7f6e\uff0c\u8bf7\u5c06\u9f20\u6807\u60ac\u505c\u5728\u590d\u9009\u6846\u4e0a\u6216\u6807\u9898\u5de6\u4fa7\u3002\u5355\u51fb\u51fa\u73b0\u7684\u9f7f\u8f6e\uff0c\u60a8\u5c06\u770b\u5230\u5982\u56fe 3-4 \u6240\u793a\u7684\u6784\u5efa\u914d\u7f6e\u9009\u62e9\u5668\u3002<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/miie.net\/img\/pro-csharp10\/images\/0304.png\" alt=\"Alt text\" \/> <\/p>\n<p>Figure 3-4. Selecting build configuration(s) for build options<br \/>\n\u56fe 3-4\u3002 \u4e3a\u6784\u5efa\u9009\u9879\u9009\u62e9\u6784\u5efa\u914d\u7f6e<\/p>\n<h2>Using the unchecked Keyword<\/h2>\n<p>\u4f7f\u7528\u672a\u9009\u4e2d\u7684\u5173\u952e\u5b57<\/p>\n<p>Now, assuming you have enabled this project-wide setting, what are you to do if you have a block of code where data loss is acceptable? Given that the \/checked flag will evaluate all arithmetic logic, C# provides the unchecked keyword to disable the throwing of an overflow exception on a case-by-case basis. This keyword\u2019s use is identical to that of the checked keyword, in that you can specify a single statement or a block of statements.<br \/>\n\u73b0\u5728\uff0c\u5047\u8bbe\u60a8\u5df2\u542f\u7528\u6b64\u9879\u76ee\u8303\u56f4\u7684\u8bbe\u7f6e\uff0c\u90a3\u4e48\u5982\u679c\u60a8\u6709\u4e00\u4e2a\u53ef\u4ee5\u63a5\u53d7\u6570\u636e\u4e22\u5931\u7684\u4ee3\u7801\u5757\uff0c\u8be5\u600e\u4e48\u529e\uff1f\u9274\u4e8e \/checked \u6807\u5fd7\u5c06\u8ba1\u7b97\u6240\u6709\u7b97\u672f\u903b\u8f91\uff0cC# \u63d0\u4f9b\u4e86 unchecked \u5173\u952e\u5b57\uff0c\u4ee5\u6839\u636e\u5177\u4f53\u60c5\u51b5\u7981\u7528\u6ea2\u51fa\u5f02\u5e38\u7684\u5f15\u53d1\u3002\u6b64\u5173\u952e\u5b57\u7684\u7528\u6cd5\u4e0e\u9009\u4e2d\u5173\u952e\u5b57\u7684\u7528\u6cd5\u76f8\u540c\uff0c\u56e0\u4e3a\u60a8\u53ef\u4ee5\u6307\u5b9a\u5355\u4e2a\u8bed\u53e5\u6216\u8bed\u53e5\u5757\u3002<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Assuming \/checked is enabled,\n\/\/ \u5047\u8bbe\u542f\u7528\u4e86 \/check\uff0c\n\/\/ this block will not trigger\n\/\/ \u6b64\u5757\u4e0d\u4f1a\u89e6\u53d1\n\/\/ a runtime exception.\n\/\/ \u8fd0\u884c\u65f6\u5f02\u5e38\u3002\nunchecked\n{\n    byte sum = (byte)(b1 + b2);\n    Console.WriteLine(&quot;sum = {0} &quot;, sum);\n}\n<\/pre>\n<\/p>\n<p>So, to summarize the C# checked and unchecked keywords, remember that the default behavior of the .NET Core runtime is to ignore arithmetic overflow\/underflow. When you want to selectively handle discrete statements, use the checked keyword. If you want to trap overflow errors throughout your application, enable the \/checked flag. Finally, the unchecked keyword can be used if you have a block of code where overflow is acceptable (and thus should not trigger a runtime exception).<br \/>\n\u56e0\u6b64\uff0c\u4e3a\u4e86\u603b\u7ed3 C# \u9009\u4e2d\u548c \u672a\u9009\u4e2d\u7684\u5173\u952e\u5b57\uff0c\u8bf7\u8bb0\u4f4f.NET Core \u8fd0\u884c\u65f6\u5ffd\u7565\u7b97\u672f\u6ea2\u51fa\/\u4e0b\u6ea2\u3002\u5982\u679c\u8981\u6709\u9009\u62e9\u5730\u5904\u7406\u79bb\u6563\u8bed\u53e5\uff0c\u8bf7\u4f7f\u7528 checked \u5173\u952e\u5b57\u3002\u5982\u679c\u8981\u5728\u6574\u4e2a\u5e94\u7528\u7a0b\u5e8f\u4e2d\u6355\u83b7\u6ea2\u51fa\u9519\u8bef\uff0c\u8bf7\u542f\u7528 \/checked \u6807\u5fd7\u3002\u6700\u540e\uff0c\u5982\u679c\u60a8\u6709\u4e00\u4e2a\u4ee3\u7801\u5757\uff0c\u5176\u4e2d\u6ea2\u51fa\u662f\u53ef\u4ee5\u63a5\u53d7\u7684\uff08\u56e0\u6b64\u4e0d\u5e94\u89e6\u53d1\u8fd0\u884c\u65f6\u5f02\u5e38\uff09\uff0c\u5219\u53ef\u4ee5\u4f7f\u7528 unchecked \u5173\u952e\u5b57\u3002<\/p>\n<h2>Understanding Implicitly Typed Local Variables<\/h2>\n<p>\u4e86\u89e3\u9690\u5f0f\u7c7b\u578b\u5c40\u90e8\u53d8\u91cf<\/p>\n<p>Up until this point in the chapter, when you have been defining local variables, you have explicitly specified the underlying data type of each variable being declared.<br \/>\n\u5728\u672c\u7ae0\u7684\u8fd9\u4e00\u70b9\u4e4b\u524d\uff0c\u5f53\u60a8\u5b9a\u4e49\u5c40\u90e8\u53d8\u91cf\u65f6\uff0c\u60a8\u5df2\u7ecf\u663e\u5f0f\u6307\u5b9a\u4e86\u8981\u58f0\u660e\u7684\u6bcf\u4e2a\u53d8\u91cf\u7684\u57fa\u7840\u6570\u636e\u7c7b\u578b\u3002<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void DeclareExplicitVars()\n{\n    \/\/ Explicitly typed local variables\n    \/\/ \u663e\u5f0f\u7c7b\u578b\u7684\u5c40\u90e8\u53d8\u91cf\n    \/\/ are declared as follows:\n    \/\/ \u58f0\u660e\u5982\u4e0b\uff1a\n    \/\/ dataType variableName = initialValue;\n    \/\/ \u6570\u636e\u7c7b\u578b\u53d8\u91cf\u540d\u79f0 = \u521d\u59cb\u503c;\n    int myInt = 0;\n    bool myBool = true;\n    string myString = &quot;Time, marches on...&quot;;\n}\n<\/pre>\n<\/p>\n<p>While many would argue that it is generally a good practice to explicitly specify the data type of each variable, the C# language does provide for implicitly typing local variables using the var keyword. The var keyword can be used in place of specifying a specific data type (such as int, bool, or string). When you do so, the compiler will automatically infer the underlying data type based on the initial value used to initialize the local data point.<br \/>\n\u867d\u7136\u8bb8\u591a\u4eba\u4f1a\u4e89\u8fa9\u8bf4\uff0c\u663e\u5f0f\u6307\u5b9a\u6bcf\u4e2a\u53d8\u91cf\u7684\u6570\u636e\u7c7b\u578b\u901a\u5e38\u662f\u4e00\u79cd\u5f88\u597d\u7684\u505a\u6cd5\uff0c\u4f46 C# \u8bed\u8a00\u786e\u5b9e\u63d0\u4f9b\u4e86\u4f7f\u7528 var \u5173\u952e\u5b57\u9690\u5f0f\u952e\u5165\u5c40\u90e8\u53d8\u91cf\u7684\u529f\u80fd\u3002var \u5173\u952e\u5b57\u53ef\u7528\u4e8e\u4ee3\u66ff\u6307\u5b9a\u7279\u5b9a\u6570\u636e\u7c7b\u578b\uff08\u5982 int\u3001bool \u6216\u5b57\u7b26\u4e32\uff09\u3002\u6267\u884c\u6b64\u64cd\u4f5c\u65f6\uff0c\u7f16\u8bd1\u5668\u5c06\u6839\u636e\u7528\u4e8e\u521d\u59cb\u5316\u672c\u5730\u6570\u636e\u70b9\u7684\u521d\u59cb\u503c\u81ea\u52a8\u63a8\u65ad\u57fa\u7840\u6570\u636e\u7c7b\u578b\u3002<\/p>\n<p>To illustrate the role of implicit typing, create a new Console Application project named ImplicitlyTypedLocalVars and add it to your solution. Update the code in Program.cs to the following:<br \/>\n\u4e3a\u4e86\u8bf4\u660e\u9690\u5f0f\u952e\u5165\u7684\u4f5c\u7528\uff0c\u8bf7\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a ImplicitlyTypedLocalVars \u7684\u65b0\u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u9879\u76ee\uff0c\u5e76\u5c06\u5176\u6dfb\u52a0\u5230\u89e3\u51b3\u65b9\u6848\u4e2d\u3002\u5c06\u7a0b\u5e8f.cs\u4e2d\u7684\u4ee3\u7801\u66f4\u65b0\u4e3a\u4ee5\u4e0b\u5185\u5bb9\uff1a<\/p>\n<p>Add the following function to demonstrate implicit declarations:<br \/>\n\u6dfb\u52a0\u4ee5\u4e0b\u51fd\u6570\u6765\u6f14\u793a\u9690\u5f0f\u58f0\u660e\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nConsole.WriteLine(&quot;***** Fun with Implicit Typing *****&quot;);\nstatic void DeclareImplicitVars()\n{\n    \/\/ Implicitly typed local variables\n    \/\/ are declared as follows:\n    \/\/ var variableName = initialValue;\n    var myInt = 0;\n    var myBool = true;\n    var myString = &quot;Time, marches on...&quot;;\n}\n<\/pre>\n<\/p>\n<blockquote><p>\n\u25a0 Note strictly speaking, var is not a C# keyword. it is permissible to declare variables, parameters, and fields named var without compile-time errors. however, when the var token is used as a data type, it is contextually treated as a keyword by the compiler.<br \/>\n\u8bf7\u6ce8\u610f\uff0c\u4e25\u683c\u6765\u8bf4\uff0cvar \u4e0d\u662f C# \u5173\u952e\u5b57\u3002\u5141\u8bb8\u58f0\u660e\u540d\u4e3a var \u7684\u53d8\u91cf\u3001\u53c2\u6570\u548c\u5b57\u6bb5\uff0c\u800c\u4e0d\u4f1a\u4ea7\u751f\u7f16\u8bd1\u65f6\u9519\u8bef\u3002\u4f46\u662f\uff0c\u5f53 var \u4ee4\u724c\u7528\u4f5c\u6570\u636e\u7c7b\u578b\u65f6\uff0c\u7f16\u8bd1\u5668\u4f1a\u5728\u4e0a\u4e0b\u6587\u4e2d\u5c06\u5176\u89c6\u4e3a\u5173\u952e\u5b57\u3002\n<\/p><\/blockquote>\n<p>In this case, the compiler is able to infer, given the initially assigned value, that myInt is, in fact, a System.Int32, myBool is a System.Boolean, and myString is indeed of type System.String. You can verify this by printing the type name via reflection. As you will see in much more detail in Chapter 17, reflection is the act of determining the composition of a type at runtime. For example, using reflection, you can determine the data type of an implicitly typed local variable. Update your method with the following code statements:<br \/>\n\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u7f16\u8bd1\u5668\u80fd\u591f\u63a8\u65ad\u51fa\uff0c\u7ed9\u5b9a\u521d\u59cb\u5206\u914d\u7684\u503c\uff0cmyInt \u5b9e\u9645\u4e0a\u662f\u4e00\u4e2a System.Int32\uff0cmyBool \u662f\u4e00\u4e2a System.Boolean\uff0c\u800c myString \u786e\u5b9e\u662f System.String \u7c7b\u578b\u3002\u53ef\u4ee5\u901a\u8fc7\u53cd\u5c04\u6253\u5370\u7c7b\u578b\u540d\u79f0\u6765\u9a8c\u8bc1\u8fd9\u4e00\u70b9\u3002\u6b63\u5982\u60a8\u5c06\u5728\u7b2c 17 \u7ae0\u4e2d\u770b\u5230\u7684\u66f4\u8be6\u7ec6\u5185\u5bb9\uff0c\u53cd\u5c04\u662f\u5728\u8fd0\u884c\u65f6\u786e\u5b9a\u7c7b\u578b\u7ec4\u5408\u7684\u884c\u4e3a\u3002\u4f8b\u5982\uff0c\u4f7f\u7528\u53cd\u5c04\uff0c\u53ef\u4ee5\u786e\u5b9a\u9690\u5f0f\u7c7b\u578b\u5316\u5c40\u90e8\u53d8\u91cf\u7684\u6570\u636e\u7c7b\u578b\u3002\u4f7f\u7528\u4ee5\u4e0b\u4ee3\u7801\u8bed\u53e5\u66f4\u65b0\u65b9\u6cd5\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void DeclareImplicitVars()\n{\n    \/\/ Implicitly typed local variables.\n    \/\/ \u9690\u5f0f\u7c7b\u578b\u7684\u5c40\u90e8\u53d8\u91cf\u3002\n    var myInt = 0;\n    var myBool = true;\n    var myString = &quot;Time, marches on...&quot;;\n\n    \/\/ Print out the underlying type.\n    \/\/ \u6253\u5370\u51fa\u57fa\u7840\u7c7b\u578b\u3002\n    Console.WriteLine(&quot;myInt is a: {0}&quot;, myInt.GetType().Name);\n    Console.WriteLine(&quot;myBool is a: {0}&quot;, myBool.GetType().Name);\n    Console.WriteLine(&quot;myString is a: {0}&quot;, myString.GetType().Name);\n}\n<\/pre>\n<\/p>\n<blockquote><p>\n\u25a0 Note  Be aware that you can use this implicit typing for any type including arrays, generic types (see Chapter 10), and your own custom types. You will see other examples of implicit typing over the course of this book.<br \/>\n\u6ce8\u610f \u8bf7\u6ce8\u610f\uff0c\u53ef\u4ee5\u5c06\u6b64\u9690\u5f0f\u7c7b\u578b\u7528\u4e8e\u4efb\u4f55\u7c7b\u578b\uff0c\u5305\u62ec\u6570\u7ec4\u3001\u6cdb\u578b\u7c7b\u578b\uff08\u8bf7\u53c2\u9605\u7b2c 10 \u7ae0\uff09\u548c\u60a8\u81ea\u5df1\u7684\u81ea\u5b9a\u4e49\u7c7b\u578b\u3002\u5728\u672c\u4e66\u7684\u8fc7\u7a0b\u4e2d\uff0c\u60a8\u5c06\u770b\u5230\u9690\u5f0f\u952e\u5165\u7684\u5176\u4ed6\u793a\u4f8b\u3002\n<\/p><\/blockquote>\n<p>If you were to call the DeclareImplicitVars() method from the top-level statements, you would find the output shown here:<br \/>\n\u5982\u679c\u8981\u4ece\u9876\u7ea7\u8bed\u53e5\u8c03\u7528 DeclareImplicitVars\uff08\uff09 \u65b9\u6cd5\uff0c\u5219\u4f1a\u627e\u5230\u5982\u4e0b\u6240\u793a\u7684\u8f93\u51fa\uff1a<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n***** Fun with Implicit Typing *****\nmyInt is a: Int32\nmyBool is a: Boolean\nmyString is a: String\n<\/pre>\n<\/p>\n<h2>Declaring Numerics Implicitly<\/h2>\n<p>\u9690\u5f0f\u58f0\u660e\u6570\u5b57<\/p>\n<p>As stated earlier, whole numbers default to integers, and floating-point numbers default to doubles. Create a new method named DeclareImplicitNumerics, and add the following code to demonstrate implicit declaration of numerics:<br \/>\n\u5982\u524d\u6240\u8ff0\uff0c\u6574\u6570\u9ed8\u8ba4\u4e3a\u6574\u6570\uff0c\u6d6e\u70b9\u6570\u9ed8\u8ba4\u4e3a\u53cc\u7cbe\u5ea6\u3002\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a DeclareImplicitNumerics \u7684\u65b0\u65b9\u6cd5\uff0c\u5e76\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\u6765\u6f14\u793a\u6570\u5b57\u7684\u9690\u5f0f\u58f0\u660e\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void DeclareImplicitNumerics()\n{\n    \/\/ Implicitly typed numeric variables.\n    \/\/ \u9690\u5f0f\u7c7b\u578b\u5316\u6570\u503c\u53d8\u91cf\u3002\n    var myUInt = 0u;\n    var myInt = 0;\n    var myLong = 0L;\n    var myDouble = 0.5; \n    var myFloat = 0.5F;\n    var myDecimal = 0.5M;\n    \/\/ Print out the underlying type.\n    \/\/ \u6253\u5370\u51fa\u57fa\u7840\u7c7b\u578b\u3002\n    Console.WriteLine(&quot;myUInt is a: {0}&quot;, myUInt.GetType().Name);\n    Console.WriteLine(&quot;myInt is a: {0}&quot;, myInt.GetType().Name);\n    Console.WriteLine(&quot;myLong is a: {0}&quot;, myLong.GetType().Name);\n    Console.WriteLine(&quot;myDouble is a: {0}&quot;, myDouble.GetType().Name);\n    Console.WriteLine(&quot;myFloat is a: {0}&quot;, myFloat.GetType().Name);\n    Console.WriteLine(&quot;myDecimal is a: {0}&quot;, myDecimal.GetType().Name);\n}\n<\/pre>\n<\/p>\n<h2>Understanding Restrictions on Implicitly Typed Variables<\/h2>\n<p>\u4e86\u89e3\u5bf9\u9690\u5f0f\u7c7b\u578b\u53d8\u91cf\u7684\u9650\u5236<\/p>\n<p>There are various restrictions regarding the use of the var keyword. First, implicit typing applies only to local variables in a method or property scope. It is illegal to use the var keyword to define return values, parameters, or field data of a custom type. For example, the following class definition will result in various compile-time errors:<br \/>\n\u5173\u4e8e var \u5173\u952e\u5b57\u7684\u4f7f\u7528\u6709\u5404\u79cd\u9650\u5236\u3002\u9996\u5148\uff0c\u9690\u5f0f\u7c7b\u578b\u4ec5\u9002\u7528\u4e8e\u65b9\u6cd5\u6216\u5c5e\u6027\u8303\u56f4\u5185\u7684\u5c40\u90e8\u53d8\u91cf\u3002\u4f7f\u7528 var \u5173\u952e\u5b57\u5b9a\u4e49\u81ea\u5b9a\u4e49\u7c7b\u578b\u7684\u8fd4\u56de\u503c\u3001\u53c2\u6570\u6216\u5b57\u6bb5\u6570\u636e\u662f\u975e\u6cd5\u7684\u3002\u4f8b\u5982\uff0c\u4ee5\u4e0b\u7c7b\u5b9a\u4e49\u5c06\u5bfc\u81f4\u5404\u79cd\u7f16\u8bd1\u65f6\u9519\u8bef\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nclass ThisWillNeverCompile\n{\n    \/\/ Error! var cannot be used as field data!\n    \/\/ \u9519\u8bef\uff01VaR \u4e0d\u80fd\u7528\u4f5c\u5b57\u6bb5\u6570\u636e\uff01\n    private var myInt = 10;\n    \/\/ Error! var cannot be used as a return value\n    \/\/ \u9519\u8bef\uff01var \u4e0d\u80fd\u7528\u4f5c\u8fd4\u56de\u503c\n    \/\/ or parameter type!\n    \/\/ \u6216\u53c2\u6570\u7c7b\u578b\uff01\n    public var MyMethod(var x, var y) { }\n}\n<\/pre>\n<\/p>\n<p>Also, local variables declared with the var keyword must be assigned an initial value at the exact time of declaration and cannot be assigned the initial value of null. This last restriction should make sense, given that the compiler cannot infer what sort of type in memory the variable would be pointing to based onlyon null.<br \/>\n\u6b64\u5916\uff0c\u4f7f\u7528 var \u5173\u952e\u5b57\u58f0\u660e\u7684\u5c40\u90e8\u53d8\u91cf\u5fc5\u987b\u5728\u58f0\u660e\u7684\u786e\u5207\u65f6\u95f4\u5206\u914d\u4e00\u4e2a\u521d\u59cb\u503c\uff0c\u5e76\u4e14\u4e0d\u80fd\u4e3a\u5176\u5206\u914d\u521d\u59cb\u503c null\u3002\u6700\u540e\u4e00\u4e2a\u9650\u5236\u5e94\u8be5\u662f\u6709\u610f\u4e49\u7684\uff0c\u56e0\u4e3a\u7f16\u8bd1\u5668\u65e0\u6cd5\u63a8\u65ad\u53d8\u91cf\u4ec5\u57fa\u4e8e\u5185\u5b58\u4e2d\u7684\u54ea\u79cd\u7c7b\u578b\u3002\u5728\u7a7a\u503c\u4e0a\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Error! Must assign a value! \n\/\/ \u9519\u8bef\uff01\u5fc5\u987b\u5206\u914d\u4e00\u4e2a\u503c\uff01\nvar myData;\n\n\/\/ Error! Must assign value at exact time of declaration! \n\/\/ \u9519\u8bef\uff01\u5fc5\u987b\u5728\u58f0\u660e\u7684\u786e\u5207\u65f6\u95f4\u5206\u914d\u503c\uff01\nvar myInt;\nmyInt = 0;\n\n\/\/ Error! Can't assign null as initial value! \n\/\/ \u9519\u8bef\uff01\u65e0\u6cd5\u5c06 null \u6307\u5b9a\u4e3a\u521d\u59cb\u503c\uff01\nvar myObj = null;\n<\/pre>\n<\/p>\n<p>It is permissible, however, to assign an inferred local variable to null after its initial assignment (provided it is a reference type).<br \/>\n\u4f46\u662f\uff0c\u5141\u8bb8\u5728\u521d\u59cb\u8d4b\u503c\u540e\u5c06\u63a8\u65ad\u7684\u5c40\u90e8\u53d8\u91cf\u8d4b\u503c\u4e3a null\uff08\u524d\u63d0\u662f\u5b83\u662f\u5f15\u7528\u7c7b\u578b\uff09\u3002<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ OK, if SportsCar is a reference type! \n\/\/ \u597d\u7684\uff0c\u5982\u679c\u8dd1\u8f66\u662f\u53c2\u8003\u7c7b\u578b\uff01\n\nvar myCar = new SportsCar();\nmyCar = null;\n<\/pre>\n<\/p>\n<p>Furthermore, it is permissible to assign the value of an implicitly typed local variable to the value of other variables, implicitly typed or not.<br \/>\n\u6b64\u5916\uff0c\u5141\u8bb8\u5c06\u9690\u5f0f\u7c7b\u578b\u5c40\u90e8\u53d8\u91cf\u7684\u503c\u5206\u914d\u7ed9\u5176\u4ed6\u53d8\u91cf\u7684\u503c\uff0c\u65e0\u8bba\u662f\u5426\u9690\u5f0f\u7c7b\u578b\u3002<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Also OK! \u4e5f\u884c\uff01\nvar myInt = 0;\n\nvar anotherInt = myInt;\nstring myString = &quot;Wake up!&quot;; \nvar myData = myString;\n<\/pre>\n<\/p>\n<p>Also, it is permissible to return an implicitly typed local variable to the caller, provided the method return type is the same underlying type as the var-defined data point.<br \/>\n\u6b64\u5916\uff0c\u5141\u8bb8\u5411\u8c03\u7528\u65b9\u8fd4\u56de\u9690\u5f0f\u7c7b\u578b\u7684\u5c40\u90e8\u53d8\u91cf\uff0c\u524d\u63d0\u662f\u8be5\u65b9\u6cd5\u8fd4\u56de\u7c7b\u578b\u4e0e var \u5b9a\u4e49\u7684\u6570\u636e\u70b9\u7684\u57fa\u7840\u7c7b\u578b\u76f8\u540c\u3002<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic int GetAnInt()\n{\n    var retVal = 9; return retVal;\n}\n<\/pre>\n<\/p>\n<h2>Implicit Typed Data Is Strongly Typed Data<\/h2>\n<p>\u9690\u5f0f\u7c7b\u578b\u5316\u6570\u636e\u662f\u5f3a\u7c7b\u578b\u6570\u636e<\/p>\n<p>Be aware that implicit typing of local variables results in strongly typed data. Therefore, use of the var keyword is not the same technique used with scripting languages (such as JavaScript or Perl) or the COM Variant data type, where a variable can hold values of different types over its lifetime in a program (often termed dynamic typing).<br \/>\n\u8bf7\u6ce8\u610f\uff0c\u5c40\u90e8\u53d8\u91cf\u7684\u9690\u5f0f\u952e\u5165\u4f1a\u5bfc\u81f4\u5f3a\u7c7b\u578b\u6570\u636e\u3002\u56e0\u6b64\uff0cvar \u5173\u952e\u5b57\u7684\u4f7f\u7528\u4e0e\u811a\u672c\u8bed\u8a00\uff08\u5982 JavaScript \u6216 Perl\uff09\u6216 COM Variant \u6570\u636e\u7c7b\u578b\u4f7f\u7528\u7684\u6280\u672f\u4e0d\u540c\uff0c\u5176\u4e2d\u53d8\u91cf\u53ef\u4ee5\u5728\u7a0b\u5e8f\u4e2d\u7684\u751f\u5b58\u671f\u5185\u4fdd\u5b58\u4e0d\u540c\u7c7b\u578b\u7684\u503c\uff08\u901a\u5e38\u79f0\u4e3a\u52a8\u6001\u7c7b\u578b\uff09\u3002<\/p>\n<blockquote><p>\n\u25a0 Note  C# does allow for dynamic typing in C# using a keyword called\u2014surprise, surprise\u2014dynamic. You will learn about this aspect of the language in Chapter 17.<br \/>\n\u6ce8\u610f C# \u786e\u5b9e\u5141\u8bb8\u5728 C# \u4e2d\u4f7f\u7528\u540d\u4e3a - \u60ca\u559c\uff0c\u60ca\u559c - \u52a8\u6001\u7684\u5173\u952e\u5b57\u8fdb\u884c\u52a8\u6001\u952e\u5165\u3002\u60a8\u5c06\u5728\u7b2c 17 \u7ae0\u4e2d\u4e86\u89e3\u8be5\u8bed\u8a00\u7684\u8fd9\u4e00\u65b9\u9762\u3002\n<\/p><\/blockquote>\n<p>Rather, type inference keeps the strongly typed aspect of the C# language and affects only the declaration of variables at compile time. After that, the data point is treated as if it were declared with that type; assigning a value of a different type into that variable will result in a compile-time error.<br \/>\n\u76f8\u53cd\uff0c\u7c7b\u578b\u63a8\u65ad\u4fdd\u7559\u4e86 C# \u8bed\u8a00\u7684\u5f3a\u7c7b\u578b\u65b9\u9762\uff0c\u5e76\u4e14\u4ec5\u5f71\u54cd\u7f16\u8bd1\u65f6\u53d8\u91cf\u7684\u58f0\u660e\u3002\u4e4b\u540e\uff0c\u6570\u636e\u70b9\u5c06\u88ab\u89c6\u4e3a\u4f7f\u7528\u8be5\u7c7b\u578b\u58f0\u660e;\u5c06\u4e0d\u540c\u7c7b\u578b\u7684\u503c\u5206\u914d\u7ed9\u8be5\u53d8\u91cf\u5c06\u5bfc\u81f4\u7f16\u8bd1\u65f6\u9519\u8bef\u3002<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void ImplicitTypingIsStrongTyping()\n{\n    \/\/ The compiler knows &quot;s&quot; is a System.String.\n    \/\/ \u7f16\u8bd1\u5668\u77e5\u9053\u201cs\u201d\u662f\u4e00\u4e2aSystem.String\u3002\n    var s = &quot;This variable can only hold string data!&quot;;\n    s = &quot;This is fine...&quot;;\n\n    \/\/ Can invoke any member of the underlying type.\n    \/\/ \u53ef\u4ee5\u8c03\u7528\u57fa\u7840\u7c7b\u578b\u7684\u4efb\u4f55\u6210\u5458\u3002 \n    string upper = s.ToUpper();\n\n    \/\/ Error! Can't assign numerical data to a string!\n    \/\/ \u9519\u8bef\uff01\u65e0\u6cd5\u4e3a\u5b57\u7b26\u4e32\u5206\u914d\u6570\u503c\u6570\u636e\uff01\n    s = 44;\n}\n<\/pre>\n<\/p>\n<h2>Understanding the Usefulness of Implicitly Typed Local Variables<\/h2>\n<p>\u4e86\u89e3\u9690\u5f0f\u7c7b\u578b\u5c40\u90e8\u53d8\u91cf\u7684\u6709\u7528\u6027<\/p>\n<p>Now that you have seen the syntax used to declare implicitly typed local variables, I am sure you are wondering when to make use of this construct. First, using var to declare local variables simply for the sake of doing so brings little to the table. Doing so can be confusing to others reading your code because it becomes harder to quickly determine the underlying data type and, therefore, more difficult to understand the overall functionality of the variable. So, if you know you need an int, declare an int!<br \/>\n\u73b0\u5728\u60a8\u5df2\u7ecf\u4e86\u89e3\u4e86\u7528\u4e8e\u58f0\u660e\u9690\u5f0f\u7c7b\u578b\u5c40\u90e8\u53d8\u91cf\u7684\u8bed\u6cd5\uff0c\u6211\u76f8\u4fe1\u60a8\u60f3\u77e5\u9053\u4f55\u65f6\u4f7f\u7528\u6b64\u6784\u9020\u3002\u9996\u5148\uff0c\u4f7f\u7528 var \u6765\u58f0\u660e\u5c40\u90e8\u53d8\u91cf\u53ea\u662f\u4e3a\u4e86\u8fd9\u6837\u505a\uff0c\u8fd9\u51e0\u4e4e\u6ca1\u6709\u4ec0\u4e48\u597d\u5904\u3002\u8fd9\u6837\u505a\u53ef\u80fd\u4f1a\u8ba9\u9605\u8bfb\u4ee3\u7801\u7684\u5176\u4ed6\u4eba\u611f\u5230\u56f0\u60d1\uff0c\u56e0\u4e3a\u5feb\u901f\u786e\u5b9a\u57fa\u7840\u6570\u636e\u7c7b\u578b\u53d8\u5f97\u66f4\u52a0\u56f0\u96be\uff0c\u56e0\u6b64\u66f4\u96be\u7406\u89e3\u53d8\u91cf\u7684\u6574\u4f53\u529f\u80fd\u3002\u6240\u4ee5\uff0c\u5982\u679c\u4f60\u77e5\u9053\u4f60\u9700\u8981\u4e00\u4e2aint\uff0c\u58f0\u660e\u4e00\u4e2aint\uff01<\/p>\n<p>However, as you will see beginning in Chapter 13, the LINQ technology set makes use of query expressions that can yield dynamically created result sets based on the format of the query itself. In these cases, implicit typing is extremely helpful because you do not need to explicitly define the type that a query may return, which in some cases would be literally impossible to do. Without getting hung up on the following LINQ example code, see whether you can figure out the underlying data type of subset:<br \/>\n\u4f46\u662f\uff0c\u6b63\u5982\u60a8\u5c06\u5728\u7b2c 13 \u7ae0\u5f00\u59cb\u770b\u5230\u7684\u90a3\u6837\uff0cLINQ \u6280\u672f\u96c6\u5229\u7528\u4e86\u67e5\u8be2\u8868\u8fbe\u5f0f\uff0c\u8fd9\u4e9b\u8868\u8fbe\u5f0f\u53ef\u4ee5\u6839\u636e\u67e5\u8be2\u672c\u8eab\u7684\u683c\u5f0f\u751f\u6210\u52a8\u6001\u521b\u5efa\u7684\u7ed3\u679c\u96c6\u3002\u5728\u8fd9\u4e9b\u60c5\u51b5\u4e0b\uff0c\u9690\u5f0f\u7c7b\u578b\u975e\u5e38\u6709\u7528\uff0c\u56e0\u4e3a\u60a8\u4e0d\u9700\u8981\u663e\u5f0f\u5b9a\u4e49\u67e5\u8be2\u53ef\u80fd\u8fd4\u56de\u7684\u7c7b\u578b\uff0c\u8fd9\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\u5b9e\u9645\u4e0a\u662f\u4e0d\u53ef\u80fd\u7684\u3002\u65e0\u9700\u7ea0\u7ed3\u4e8e\u4ee5\u4e0b LINQ \u793a\u4f8b\u4ee3\u7801\uff0c\u8bf7\u67e5\u770b\u662f\u5426\u53ef\u4ee5\u786e\u5b9a\u5b50\u96c6\u7684\u57fa\u7840\u6570\u636e\u7c7b\u578b\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void LinqQueryOverInts()\n{\n    int&#x5B;] numbers = { 10, 20, 30, 40, 1, 2, 3, 8 };\n    \/\/ LINQ query!\n    var subset = from i in numbers where i &lt; 10 select i;\n    Console.Write(&quot;Values in subset: &quot;);\n    foreach (var i in subset)\n    {\n        Console.Write(&quot;{0} &quot;, i);\n    }\n    Console.WriteLine();\n    \/\/ Hmm...what type is subset?\n    \/\/ \u55ef\u3002\u3002\u3002\u5b50\u96c6\u662f\u4ec0\u4e48\u7c7b\u578b\uff1f\n    Console.WriteLine(&quot;subset is a: {0}&quot;, subset.GetType().Name);\n    Console.WriteLine(&quot;subset is defined in: {0}&quot;, subset.GetType().Namespace);\n}\n<\/pre>\n<\/p>\n<p>You might be assuming that the subset data type is an array of integers. That seems to be the case, but, in fact, it is a low-level LINQ data type that you would never know about unless you have been doing LINQ for a long time or you open the compiled image in ildasm.exe. The good news is that when you are using LINQ, you seldom (if ever) care about the underlying type of the query\u2019s return value; you will simply assign the value to an implicitly typed local variable.<br \/>\n\u60a8\u53ef\u80fd\u5047\u8bbe\u5b50\u96c6\u6570\u636e\u7c7b\u578b\u662f\u6574\u6570\u6570\u7ec4\u3002\u60c5\u51b5\u4f3c\u4e4e\u662f\u8fd9\u6837\uff0c\u4f46\u5b9e\u9645\u4e0a\uff0c\u5b83\u662f\u4e00\u79cd\u4f4e\u7ea7 LINQ \u6570\u636e\u7c7b\u578b\uff0c\u9664\u975e\u60a8\u5df2\u7ecf\u6267\u884c LINQ \u5f88\u957f\u65f6\u95f4\u6216\u5728 ildasm.exe \u4e2d\u6253\u5f00\u7f16\u8bd1\u540e\u7684\u6620\u50cf\uff0c\u5426\u5219\u60a8\u6c38\u8fdc\u4e0d\u4f1a\u77e5\u9053\u5b83\u3002\u597d\u6d88\u606f\u662f\uff0c\u5728\u4f7f\u7528 LINQ \u65f6\uff0c\u60a8\u5f88\u5c11\uff08\u5982\u679c\u6709\u7684\u8bdd\uff09\u5173\u5fc3\u67e5\u8be2\u8fd4\u56de\u503c\u7684\u57fa\u7840\u7c7b\u578b;\u60a8\u53ea\u9700\u5c06\u503c\u5206\u914d\u7ed9\u9690\u5f0f\u7c7b\u578b\u7684\u5c40\u90e8\u53d8\u91cf\u3002<\/p>\n<p>In fact, it could be argued that the only time you would make use of the var keyword is when defining data returned from a LINQ query. Remember, if you know you need an int, just declare an int! Overuse of implicit typing (via the var keyword) is considered by most developers to be poor style in production code.<br \/>\n\u4e8b\u5b9e\u4e0a\uff0c\u53ef\u4ee5\u8bf4\uff0c\u552f\u4e00\u4f7f\u7528 var \u5173\u952e\u5b57\u7684\u65f6\u95f4\u662f\u5728\u5b9a\u4e49\u4ece LINQ \u67e5\u8be2\u8fd4\u56de\u7684\u6570\u636e\u65f6\u3002\u8bb0\u4f4f\uff0c\u5982\u679c\u4f60\u77e5\u9053\u4f60\u9700\u8981\u4e00\u4e2aint\uff0c\u53ea\u9700\u58f0\u660e\u4e00\u4e2aint\uff01\u5927\u591a\u6570\u5f00\u53d1\u4eba\u5458\u8ba4\u4e3a\u8fc7\u5ea6\u4f7f\u7528\u9690\u5f0f\u7c7b\u578b\uff08\u901a\u8fc7 var \u5173\u952e\u5b57\uff09\u662f\u751f\u4ea7\u4ee3\u7801\u4e2d\u7684\u4e0d\u826f\u98ce\u683c\u3002<\/p>\n<h2>Working with C# Iteration Constructs<\/h2>\n<p>\u4f7f\u7528 C# \u8fed\u4ee3\u6784\u9020<\/p>\n<p>All programming languages provide ways to repeat blocks of code until a terminating condition has been met. Regardless of which language you have used in the past, I would guess the C# iteration statements should not raise too many eyebrows and should require little explanation. C# provides the following four iteration constructs:<br \/>\n\u6240\u6709\u7f16\u7a0b\u8bed\u8a00\u90fd\u63d0\u4f9b\u4e86\u91cd\u590d\u4ee3\u7801\u5757\u7684\u65b9\u6cd5\uff0c\u76f4\u5230\u6ee1\u8db3\u7ec8\u6b62\u6761\u4ef6\u3002\u65e0\u8bba\u60a8\u8fc7\u53bb\u4f7f\u7528\u54ea\u79cd\u8bed\u8a00\uff0c\u6211\u731c C# \u8fed\u4ee3\u8bed\u53e5\u90fd\u4e0d\u5e94\u8be5\u5f15\u8d77\u592a\u591a\u7684\u6ce8\u610f\uff0c\u5e76\u4e14\u5e94\u8be5\u4e0d\u9700\u8981\u89e3\u91ca\u3002C# \u63d0\u4f9b\u4ee5\u4e0b\u56db\u4e2a\u8fed\u4ee3\u6784\u9020\uff1a<\/p>\n<ul>\n<li>for loop<\/li>\n<li>foreach\/in loop<\/li>\n<li>while loop<\/li>\n<li>do\/while loop<\/li>\n<\/ul>\n<p>Let\u2019s quickly examine each looping construct in turn, using a new Console Application project named IterationsAndDecisions.<br \/>\n\u8ba9\u6211\u4eec\u4f7f\u7528\u540d\u4e3a IterationsAndDecisions \u7684\u65b0\u63a7\u5236\u53f0\u5e94\u7528\u7a0b\u5e8f\u9879\u76ee\u4f9d\u6b21\u5feb\u901f\u68c0\u67e5\u6bcf\u4e2a\u5faa\u73af\u6784\u9020\u3002<\/p>\n<blockquote><p>\n\u25a0 Note  i will keep this section of the chapter short and to the point, as i am assuming you have experience using similar keywords (if, for, switch, etc.) in your current programming language. if you require more information, look up the topics \u201citeration statements (C# reference),\u201d \u201cJump statements (C# reference),\u201d and \u201cselection statements (C# reference)\u201d within the C# documentation.<br \/>\n\u8bf7\u6ce8\u610f\uff0c\u6211\u5c06\u4fdd\u6301\u672c\u7ae0\u7684\u8fd9\u4e00\u90e8\u5206\u7b80\u77ed\u800c\u4e2d\u80af\uff0c\u56e0\u4e3a\u6211\u5047\u8bbe\u60a8\u6709\u5728\u5f53\u524d\u7f16\u7a0b\u8bed\u8a00\u4e2d\u4f7f\u7528\u7c7b\u4f3c\u5173\u952e\u5b57\uff08if\uff0cfor\uff0cswitch\u7b49\uff09\u7684\u7ecf\u9a8c\u3002\u5982\u679c\u9700\u8981\u66f4\u591a\u4fe1\u606f\uff0c\u8bf7\u5728 C# \u6587\u6863\u4e2d\u67e5\u627e\u4e3b\u9898\u201c\u8fed\u4ee3\u8bed\u53e5\uff08C# \u53c2\u8003\uff09\u201d\u3001\u201c\u8df3\u8f6c\u8bed\u53e5\uff08C# \u53c2\u8003\uff09\u201d\u548c\u201c\u9009\u62e9\u8bed\u53e5\uff08C# \u53c2\u8003\uff09\u201d\u3002\n<\/p><\/blockquote>\n<h3>Using the for Loop<\/h3>\n<p>\u4f7f\u7528 for \u5faa\u73af<\/p>\n<p>When you need to iterate over a block of code a fixed number of times, the for statement provides a good deal of flexibility. In essence, you are able to specify how many times a block of code repeats itself, as well as the terminating condition. Without belaboring the point, here is a sample of the syntax:<br \/>\n\u5f53\u60a8\u9700\u8981\u5bf9\u4ee3\u7801\u5757\u8fdb\u884c\u56fa\u5b9a\u6b21\u6570\u7684\u8fed\u4ee3\u65f6\uff0cfor \u8bed\u53e5\u63d0\u4f9b\u4e86\u5f88\u5927\u7684\u7075\u6d3b\u6027\u3002\u5b9e\u8d28\u4e0a\uff0c\u60a8\u53ef\u4ee5\u6307\u5b9a\u4ee3\u7801\u5757\u91cd\u590d\u7684\u6b21\u6570\u4ee5\u53ca\u7ec8\u6b62\u6761\u4ef6\u3002\u5728\u4e0d\u8d58\u8ff0\u8fd9\u4e00\u70b9\u7684\u60c5\u51b5\u4e0b\uff0c\u4e0b\u9762\u662f\u8bed\u6cd5\u793a\u4f8b\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \n\/\/ A basic for loop.\n\/\/ \u4e00\u4e2a\u57fa\u672c\u7684 for \u5faa\u73af\u3002\nstatic void ForLoopExample()\n{\n    \/\/ Note! &quot;i&quot; is only visible within the scope of the for loop.\n    \/\/ \u6ce8\u610f\uff01\u201ci\u201d\u4ec5\u5728 for \u5faa\u73af\u7684\u8303\u56f4\u5185\u53ef\u89c1\u3002\n    for (int i = 0; i &lt; 4; i++)\n    {\n        Console.WriteLine(&quot;Number is: {0} &quot;, i);\n    }\n    \/\/ &quot;i&quot; is not visible here.\n    \/\/\u201ci\u201d\u5728\u8fd9\u91cc\u4e0d\u53ef\u89c1\u3002\n}\n<\/pre>\n<\/p>\n<p>All your old C, C++, and Java tricks still hold when building a C# for statement. You can create complex terminating conditions, build endless loops, loop in reverse (via the -- operator), and use the goto, continue, and break jump keywords.<br \/>\n\u5728\u6784\u5efa C# for \u8bed\u53e5\u65f6\uff0c\u6240\u6709\u65e7\u7684 C\u3001C++ \u548c Java \u6280\u5de7\u4ecd\u7136\u9002\u7528\u3002\u60a8\u53ef\u4ee5\u521b\u5efa\u590d\u6742\u7684\u7ec8\u6b62\u6761\u4ef6\u3001\u6784\u5efa\u65e0\u9650\u5faa\u73af\u3001\u53cd\u5411\u5faa\u73af\uff08\u901a\u8fc7 -- \u8fd0\u7b97\u7b26\uff09\uff0c\u5e76\u4f7f\u7528 goto\u3001\u7ee7\u7eed\u548c\u4e2d\u65ad\u8df3\u8f6c\u5173\u952e\u5b57\u3002<\/p>\n<h2>Using the foreach Loop\u4f7f\u7528 foreach \u5faa\u73af<\/h2>\n<p>The C# foreach keyword allows you to iterate over all items in a container without the need to test for an upper limit. Unlike a for loop, however, the foreach loop will walk the container only in a linear (n+1) fashion (thus, you cannot go backward through the container, skip every third element, or whatnot).<br \/>\nC# foreach \u5173\u952e\u5b57\u5141\u8bb8\u5faa\u73af\u8bbf\u95ee\u5bb9\u5668\u4e2d\u7684\u6240\u6709\u9879\uff0c\u800c\u65e0\u9700\u6d4b\u8bd5\u4e0a\u9650\u3002\u4f46\u662f\uff0c\u4e0e for \u5faa\u73af\u4e0d\u540c\u7684\u662f\uff0cforeach \u5faa\u73af\u5c06\u4ec5\u4ee5\u7ebf\u6027 \uff08n+1\uff09 \u65b9\u5f0f\u904d\u5386\u5bb9\u5668\uff08\u56e0\u6b64\uff0c\u60a8\u4e0d\u80fd\u5411\u540e\u6d4f\u89c8\u5bb9\u5668\uff0c\u8df3\u8fc7\u6bcf\u9694\u4e09\u4e2a\u5143\u7d20\uff0c\u6216\u8005\u5176\u4ed6\u4ec0\u4e48\uff09\u3002<\/p>\n<p>However, when you simply need to walk a collection item by item, the foreach loop is the perfect choice. Here are two examples using foreach\u2014one to traverse an array of strings and the other to traverse an array of integers. Notice that the data type before the in keyword represents the type of data in the container.<br \/>\n\u4f46\u662f\uff0c\u5f53\u60a8\u53ea\u9700\u8981\u9010\u9879\u6d4f\u89c8\u96c6\u5408\u65f6\uff0cforeach \u5faa\u73af\u662f\u5b8c\u7f8e\u7684\u9009\u62e9\u3002\u4e0b\u9762\u662f\u4e24\u4e2a\u4f7f\u7528 foreach \u7684\u793a\u4f8b\uff0c\u4e00\u4e2a\u7528\u4e8e\u904d\u5386\u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u53e6\u4e00\u4e2a\u7528\u4e8e\u904d\u5386\u6574\u6570\u6570\u7ec4\u3002\u8bf7\u6ce8\u610f\uff0cin \u5173\u952e\u5b57\u4e4b\u524d\u7684\u6570\u636e\u7c7b\u578b\u8868\u793a\u5bb9\u5668\u4e2d\u7684\u6570\u636e\u7c7b\u578b\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \n\/\/ Iterate array items using foreach.\n\/\/ \u4f7f\u7528 foreach \u8fed\u4ee3\u6570\u7ec4\u9879\u3002\nstatic void ForEachLoopExample()\n{\n    string&#x5B;] carTypes = { &quot;Ford&quot;, &quot;BMW&quot;, &quot;Yugo&quot;, &quot;Honda&quot; };\n    foreach (string c in carTypes)\n    {\n        Console.WriteLine(c);\n    }\n    int&#x5B;] myInts = { 10, 20, 30, 40 };\n    foreach (int i in myInts)\n    {\n        Console.WriteLine(i);\n    }\n}\n<\/pre>\n<\/p>\n<p>The item after the in keyword can be a simple array (seen here) or, more specifically, any class implementing the IEnumerable interface. As you will see in Chapter 10, the .NET Core base class libraries ship with a number of collections that contain implementations of common abstract data types (ADTs). Any of these items (such as the generic List<T>) can be used within a foreach loop.<br \/>\nin \u5173\u952e\u5b57\u540e\u9762\u7684\u9879\u53ef\u4ee5\u662f\u4e00\u4e2a\u7b80\u5355\u7684\u6570\u7ec4\uff08\u89c1\u6b64\u5904\uff09\uff0c\u6216\u8005\u66f4\u5177\u4f53\u5730\u8bf4\uff0c\u662f\u5b9e\u73b0 IEnumerable \u63a5\u53e3\u7684\u4efb\u4f55\u7c7b\u3002\u6b63\u5982\u60a8\u5c06\u5728\u7b2c 10 \u7ae0\u4e2d\u770b\u5230\u7684\uff0c.NET Core \u57fa\u7c7b\u5e93\u9644\u5e26\u4e86\u8bb8\u591a\u96c6\u5408\uff0c\u8fd9\u4e9b\u96c6\u5408\u5305\u542b\u5e38\u89c1\u62bd\u8c61\u6570\u636e\u7c7b\u578b \uff08ADT\uff09 \u7684\u5b9e\u73b0\u3002\u8fd9\u4e9b\u9879\u4e2d\u7684\u4efb\u4f55\u4e00\u9879\uff08\u5982\u901a\u7528 List<T>\uff09\u90fd\u53ef\u4ee5\u5728 foreach \u5faa\u73af\u4e2d\u4f7f\u7528\u3002<\/p>\n<h2>Using Implicit Typing Within foreach Constructs<\/h2>\n<p>\u5728 foreach \u6784\u9020\u4e2d\u4f7f\u7528\u9690\u5f0f\u7c7b\u578b<\/p>\n<p>It is also possible to use implicit typing within a foreach looping construct. As you would expect, the compiler will correctly infer the correct \u201ctype of type.\u201d Recall the LINQ example method shown earlier in this chapter. Given that you do not know the exact underlying data type of the subset variable, you can iterate over the result set using implicit typing.<br \/>\n\u4e5f\u53ef\u4ee5\u5728 foreach \u5faa\u73af\u6784\u9020\u4e2d\u4f7f\u7528\u9690\u5f0f\u7c7b\u578b\u3002\u5982\u60a8\u6240\u6599\uff0c\u7f16\u8bd1\u5668\u5c06\u6b63\u786e\u63a8\u65ad\u6b63\u786e\u7684\u201c\u7c7b\u578b\u7c7b\u578b\u201d\u3002\u56de\u987e\u672c\u7ae0\u524d\u9762\u6240\u793a\u7684 LINQ \u793a\u4f8b\u65b9\u6cd5\u3002\u5982\u679c\u60a8\u4e0d\u77e5\u9053\u5b50\u96c6\u53d8\u91cf\u7684\u786e\u5207\u57fa\u7840\u6570\u636e\u7c7b\u578b\uff0c\u5219\u53ef\u4ee5\u4f7f\u7528\u9690\u5f0f\u7c7b\u578b\u5faa\u73af\u8bbf\u95ee\u7ed3\u679c\u96c6\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \nstatic void LinqQueryOverInts()\n{\n    int&#x5B;] numbers = { 10, 20, 30, 40, 1, 2, 3, 8 };\n    \/\/ LINQ query!\n    var subset = from i in numbers where i &lt; 10 select i;\n    Console.Write(&quot;Values in subset: &quot;);\n    foreach (var i in subset)\n    {\n        Console.Write(&quot;{0} &quot;, i);\n    }\n}\n<\/pre>\n<\/p>\n<h3>Using the while and do\/while Looping Constructs<\/h3>\n<p>\u4f7f\u7528 while \u548c do\/while \u5faa\u73af\u6784\u9020<\/p>\n<p>The while looping construct is useful should you want to execute a block of statements until some terminating condition has been reached. Within the scope of a while loop, you will need to ensure this terminating event is indeed established; otherwise, you will be stuck in an endless loop. In the following example, the message &quot;In while loop&quot; will be continuously printed until the user terminates the loop by entering yes at the command prompt:<br \/>\n\u5982\u679c\u8981\u6267\u884c\u8bed\u53e5\u5757\u76f4\u5230\u8fbe\u5230\u67d0\u4e2a\u7ec8\u6b62\u6761\u4ef6\uff0c\u5219 while \u5faa\u73af\u6784\u9020\u5f88\u6709\u7528\u3002\u5728 while \u5faa\u73af\u7684\u8303\u56f4\u5185\uff0c\u60a8\u9700\u8981\u786e\u4fdd\u786e\u5b9e\u5efa\u7acb\u4e86\u6b64\u7ec8\u6b62\u4e8b\u4ef6;\u5426\u5219\uff0c\u60a8\u5c06\u9677\u5165\u65e0\u4f11\u6b62\u7684\u5faa\u73af\u3002\u5728\u4ee5\u4e0b\u793a\u4f8b\u4e2d\uff0c\u5c06\u8fde\u7eed\u6253\u5370\u6d88\u606f\u201cIn while loop\u201d\uff0c\u76f4\u5230\u7528\u6237\u901a\u8fc7\u5728\u547d\u4ee4\u63d0\u793a\u7b26\u4e0b\u8f93\u5165 yes \u6765\u7ec8\u6b62\u5faa\u73af\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \nstatic void WhileLoopExample()\n{\n    string userIsDone = &quot;&quot;;\n    \/\/ Test on a lower-class copy of the string.\n    \/\/ \u5728\u5b57\u7b26\u4e32\u7684\u8f83\u4f4e\u7c7b\u526f\u672c\u4e0a\u8fdb\u884c\u6d4b\u8bd5\u3002\n    while (userIsDone.ToLower() != &quot;yes&quot;)\n    {\n        Console.WriteLine(&quot;In while loop&quot;);\n        Console.Write(&quot;Are you done? &#x5B;yes] &#x5B;no]: &quot;);\n        userIsDone = Console.ReadLine();\n    }\n}\n<\/pre>\n<\/p>\n<p>Closely related to the while loop is the do\/while statement. Like a simple while loop, do\/while is used when you need to perform some action an undetermined number of times. The difference is that do\/while loops are guaranteed to execute the corresponding block of code at least once. In contrast, it is possible that a simple while loop may never execute if the terminating condition is false from the onset.<br \/>\n\u4e0e while \u5faa\u73af\u5bc6\u5207\u76f8\u5173\u7684\u662f do\/while \u8bed\u53e5\u3002 \u5c31\u50cf\u4e00\u4e2a\u7b80\u5355\u7684 while \u5faa\u73af\u4e00\u6837\uff0c\u5f53\u60a8\u9700\u8981\u6267\u884c\u67d0\u4e9b\u64cd\u4f5c\u7684\u6b21\u6570\u4e0d\u786e\u5b9a\u65f6\uff0c\u4f7f\u7528 do\/while\u3002 \u4e0d\u540c\u4e4b\u5904\u5728\u4e8e do\/while \u5faa\u73af\u4fdd\u8bc1\u81f3\u5c11\u6267\u884c\u4e00\u6b21\u76f8\u5e94\u7684\u4ee3\u7801\u5757\u3002\u76f8\u53cd\uff0c\u5982\u679c\u7ec8\u6b62\u6761\u4ef6\u4ece\u4e00\u5f00\u59cb\u5c31\u4e3a false\uff0c\u5219\u7b80\u5355\u7684 while \u5faa\u73af\u53ef\u80fd\u6c38\u8fdc\u4e0d\u4f1a\u6267\u884c\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \nstatic void DoWhileLoopExample()\n{\n    string userIsDone = &quot;&quot;;\n    do\n    {\n        Console.WriteLine(&quot;In do\/while loop&quot;);\n        Console.Write(&quot;Are you done? &#x5B;yes] &#x5B;no]: &quot;);\n        userIsDone = Console.ReadLine();\n    } while (userIsDone.ToLower() != &quot;yes&quot;); \/\/ Note the semicolon!\n}\n<\/pre>\n<\/p>\n<h2>A Quick Discussion About Scope<\/h2>\n<p>\u5173\u4e8e\u8303\u56f4\u7684\u5feb\u901f\u8ba8\u8bba<\/p>\n<p>Like all languages based on C (C#, Java, etc.), a scope is created using curly braces. You have already seen this in many of the examples so far, including namespaces, classes, and methods. The iteration and decision constructs also operate in a scope, as in the following example:<br \/>\n\u50cf\u6240\u6709\u57fa\u4e8e C\uff08C#\u3001Java \u7b49\uff09\u7684\u8bed\u8a00\u4e00\u6837\uff0c\u4f5c\u7528\u57df\u662f\u4f7f\u7528\u5927\u62ec\u53f7\u521b\u5efa\u7684\u3002\u5230\u76ee\u524d\u4e3a\u6b62\uff0c\u60a8\u5df2\u7ecf\u5728\u8bb8\u591a\u793a\u4f8b\u4e2d\u770b\u5230\u4e86\u8fd9\u4e00\u70b9\uff0c\u5305\u62ec\u547d\u540d\u7a7a\u95f4\u3001\u7c7b\u548c\u65b9\u6cd5\u3002\u8fed\u4ee3\u548c\u51b3\u7b56\u6784\u9020\u4e5f\u5728\u4f5c\u7528\u57df\u4e2d\u8fd0\u884c\uff0c\u5982\u4ee5\u4e0b\u793a\u4f8b\u6240\u793a\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \nfor(int i = 0; i &lt; 4; i++)\n{\n    Console.WriteLine(&quot;Number is: {0} &quot;, i);\n}\n<\/pre>\n<\/p>\n<p>For these constructs (both in the previous section and the next section), it is permissible to not use curly braces. In other words, the following code is exactly the same as the previous example:<br \/>\n\u5bf9\u4e8e\u8fd9\u4e9b\u6784\u9020\uff08\u5728\u4e0a\u4e00\u8282\u548c\u4e0b\u4e00\u8282\u4e2d\uff09\uff0c\u5141\u8bb8\u4e0d\u4f7f\u7528\u5927\u62ec\u53f7\u3002\u6362\u53e5\u8bdd\u8bf4\uff0c\u4ee5\u4e0b\u4ee3\u7801\u4e0e\u524d\u9762\u7684\u793a\u4f8b\u5b8c\u5168\u76f8\u540c\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \nfor(int i = 0; i &lt; 4; i++) \n    Console.WriteLine(&quot;Number is: {0} &quot;, i);\n<\/pre>\n<\/p>\n<p>While this is permissible, it is typically not a good idea. The problem is not the one-line statement, but the statement that goes from one line to more than one line. Without the braces, mistakes could be made when expanding the code within the iteration\/decision constructs. For example, the following two examples are not the same:<br \/>\n\u867d\u7136\u8fd9\u662f\u5141\u8bb8\u7684\uff0c\u4f46\u8fd9\u901a\u5e38\u4e0d\u662f\u4e00\u4e2a\u597d\u4e3b\u610f\u3002\u95ee\u9898\u4e0d\u5728\u4e8e\u5355\u884c\u8bed\u53e5\uff0c\u800c\u5728\u4e8e\u4ece\u4e00\u884c\u5230\u591a\u884c\u7684\u8bed\u53e5\u3002\u5982\u679c\u6ca1\u6709\u5927\u62ec\u53f7\uff0c\u5728\u8fed\u4ee3\/\u51b3\u7b56\u7ed3\u6784\u4e2d\u6269\u5c55\u4ee3\u7801\u65f6\u53ef\u80fd\u4f1a\u51fa\u9519\u3002\u4f8b\u5982\uff0c\u4ee5\u4e0b\u4e24\u4e2a\u793a\u4f8b\u5e76\u4e0d\u76f8\u540c\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \n\/\/ \u5e26\u62ec\u53f7\nfor (int i = 0; i &lt; 4; i++)\n{\n    Console.WriteLine(&quot;Number is: {0} &quot;, i);\n    Console.WriteLine(&quot;Number plus 1 is: {0} &quot;, i + 1);\n}\n\n\/\/ \u4e0d\u5e26\u62ec\u53f7\nfor (int i = 0; i &lt; 4; i++)\n    Console.WriteLine(&quot;Number is: {0} &quot;, i);\n    Console.WriteLine(&quot;Number plus 1 is: {0} &quot;, i + 1);\n<\/pre>\n<\/p>\n<p>If you are lucky (like in this example), the additional line of code generates a compilation error, since the variable i is defined only in the scope of the for loop. If you are unlucky, you are executing code that does not get flagged as a compiler error, but is a logic error, which is harder to find and debug.<br \/>\n\u5982\u679c\u5e78\u8fd0\u7684\u8bdd\uff08\u5982\u672c\u4f8b\u6240\u793a\uff09\uff0c\u989d\u5916\u7684\u4ee3\u7801\u884c\u4f1a\u751f\u6210\u7f16\u8bd1\u9519\u8bef\uff0c\u56e0\u4e3a\u53d8\u91cf i \u4ec5\u5728 for \u5faa\u73af\u7684\u8303\u56f4\u5185\u5b9a\u4e49\u3002\u5982\u679c\u8fd0\u6c14\u4e0d\u597d\uff0c\u60a8\u6b63\u5728\u6267\u884c\u7684\u4ee3\u7801\u4e0d\u4f1a\u88ab\u6807\u8bb0\u4e3a\u7f16\u8bd1\u5668\u9519\u8bef\uff0c\u800c\u662f\u903b\u8f91\u9519\u8bef\uff0c\u8fd9\u66f4\u96be\u67e5\u627e\u548c\u8c03\u8bd5\u3002<\/p>\n<h2>Working with Decision Constructs and the Relational\/ Equality Operators<\/h2>\n<p>\u4f7f\u7528\u51b3\u7b56\u6784\u9020\u548c\u5173\u7cfb\/\u76f8\u7b49\u8fd0\u7b97\u7b26<\/p>\n<p>Now that you can iterate over a block of statements, the next related concept is how to control the flow of program execution. C# defines two simple constructs to alter the flow of your program, based on various contingencies:<br \/>\n\u73b0\u5728\u60a8\u53ef\u4ee5\u8fed\u4ee3\u8bed\u53e5\u5757\uff0c\u4e0b\u4e00\u4e2a\u76f8\u5173\u6982\u5ff5\u662f\u5982\u4f55\u63a7\u5236\u7a0b\u5e8f\u6267\u884c\u6d41\u3002C# \u5b9a\u4e49\u4e86\u4e24\u4e2a\u7b80\u5355\u7684\u6784\u9020\uff0c\u7528\u4e8e\u6839\u636e\u5404\u79cd\u610f\u5916\u60c5\u51b5\u66f4\u6539\u7a0b\u5e8f\u6d41\uff1a<\/p>\n<ul>\n<li>The if\/else statement<\/li>\n<li>The switch statement<\/li>\n<\/ul>\n<blockquote><p>\n\u25a0 Note  C# 7 extends the is expression and switch statements with a technique called pattern matching. the basics of how these extensions affect if\/else and switch statements are shown here for completeness. these extensions will make more sense after reading Chapter 6, which covers base class\/derived class rules, casting, and the standard is operator.<br \/>\n\u6ce8\u610f C# 7 \u4f7f\u7528\u79f0\u4e3a\u6a21\u5f0f\u5339\u914d\u7684\u6280\u672f\u6269\u5c55\u4e86 is \u8868\u8fbe\u5f0f\u548c\u5f00\u5173\u8bed\u53e5\u3002\u4e3a\u4e86\u5b8c\u6574\u8d77\u89c1\uff0c\u6b64\u5904\u663e\u793a\u4e86\u8fd9\u4e9b\u6269\u5c55\u5982\u4f55\u5f71\u54cd if\/else \u548c switch \u8bed\u53e5\u7684\u57fa\u7840\u77e5\u8bc6\u3002 \u9605\u8bfb\u7b2c 6 \u7ae0\u540e\uff0c\u8fd9\u4e9b\u6269\u5c55\u5c06\u66f4\u6709\u610f\u4e49\uff0c\u8be5\u7ae0\u6db5\u76d6\u4e86\u57fa\u7c7b\/\u6d3e\u751f\u7c7b\u89c4\u5219\u3001\u5f3a\u5236\u8f6c\u6362\u548c\u6807\u51c6 IS \u8fd0\u7b97\u7b26\u3002\n<\/p><\/blockquote>\n<h3>Using the if\/else Statement<\/h3>\n<p>\u4f7f\u7528 if\/else \u8bed\u53e5<\/p>\n<p>First up is the if\/else statement. Unlike in C and C++, the if\/else statement in C# operates only on Boolean expressions, not ad hoc values such as \u20131 or 0.<br \/>\n\u9996\u5148\u662f if\/else \u8bed\u53e5\u3002\u4e0e C \u548c C++ \u4e0d\u540c\uff0cC# \u4e2d\u7684 if\/else \u8bed\u53e5\u4ec5\u5bf9\u5e03\u5c14\u8868\u8fbe\u5f0f\u8fdb\u884c\u64cd\u4f5c\uff0c\u800c\u4e0d\u5bf9 \u20131 \u6216 0 \u7b49\u5373\u5e2d\u503c\u8fdb\u884c\u64cd\u4f5c\u3002<\/p>\n<h3>Using Equality and Relational Operators<\/h3>\n<p>\u4f7f\u7528\u76f8\u7b49\u8fd0\u7b97\u7b26\u548c\u5173\u7cfb\u8fd0\u7b97\u7b26<\/p>\n<p>C# if\/else statements typically involve the use of the C# operators shown in Table 3-8 to obtain a literal Boolean value.<br \/>\nC# if\/else \u8bed\u53e5\u901a\u5e38\u6d89\u53ca\u4f7f\u7528\u8868 3-8 \u4e2d\u6240\u793a\u7684 C# \u8fd0\u7b97\u7b26\u6765\u83b7\u53d6\u6587\u672c\u5e03\u5c14\u503c\u3002<\/p>\n<p>Table 3-8. C# Relational and Equality Operators<br \/>\n\u8868 3-8. C# \u5173\u7cfb\u8fd0\u7b97\u7b26\u548c\u76f8\u7b49\u8fd0\u7b97\u7b26<\/p>\n<table>\n<tr>\n<td>C# Equality\/Relational Operator<\/td>\n<td>Example Usage<\/td>\n<td>Meaning in Life<\/td>\n<\/tr>\n<tr>\n<td>==<\/td>\n<td>if(age == 30)<\/td>\n<td>Returns true only if each expression is the same<br \/>\n        \u4ec5\u5f53\u6bcf\u4e2a\u8868\u8fbe\u5f0f\u76f8\u540c\u65f6\u624d\u8fd4\u56de true<\/td>\n<\/tr>\n<tr>\n<td>!=<\/td>\n<td>if(&quot;Foo&quot; != myStr)<\/td>\n<td>Returns true only if each expression is different<br \/>\n        \u4ec5\u5f53\u6bcf\u4e2a\u8868\u8fbe\u5f0f\u4e0d\u540c\u65f6\u624d\u8fd4\u56de true<\/td>\n<\/tr>\n<tr>\n<td>&lt;<\/td>\n<td>if(bonus &lt; 2000)<\/td>\n<td>Returns true if expression A (bonus) is less than expression B (2000)<br \/>\n        \u5982\u679c\u8868\u8fbe\u5f0f A\uff08\u5956\u91d1\uff09\u5c0f\u4e8e\u8868\u8fbe\u5f0f B \uff082000)<\/td>\n<\/tr>\n<tr>\n<td>&gt;<\/td>\n<td>if(bonus &gt; 2000)<\/td>\n<td>Returns true if expression A (bonus) is greater than expression B (2000)<br \/>\n        \u5982\u679c\u8868\u8fbe\u5f0f A\uff08\u5956\u91d1\uff09\u5927\u4e8e\u8868\u8fbe\u5f0f B \uff082000\uff09<\/td>\n<\/tr>\n<tr>\n<td>&lt;=<\/td>\n<td>if(bonus &lt;= 2000)<\/td>\n<td>Returns true if expression A (bonus) is less than or equal to expression B (2000)<br \/>\n        \u5982\u679c\u8868\u8fbe\u5f0f A\uff08\u5956\u91d1\uff09\u5c0f\u4e8e\u6216\u7b49\u4e8e\u8868\u8fbe\u5f0f B \uff082000\uff09<\/td>\n<\/tr>\n<tr>\n<td>&gt;=<\/td>\n<td>if(bonus &gt;= 2000)<\/td>\n<td>Returns true if expression A (bonus) is greater than or equal to expression B (2000)<br \/>\n        \u5982\u679c\u8868\u8fbe\u5f0f A\uff08\u5956\u91d1\uff09\u5927\u4e8e\u6216\u7b49\u4e8e\u8868\u8fbe\u5f0f B \uff082000\uff09<\/td>\n<\/tr>\n<\/table>\n<p>Again, C and C++ programmers need to be aware that the old tricks of testing a condition for a value not equal to zero will not work in C#. Let\u2019s say you want to see whether the string you are working with is longer than zero characters. You might be tempted to write this:<br \/>\n\u5982\u679c\u8868\u8fbe\u5f0f A\uff08\u5956\u91d1\uff09\u5927\u4e8e\u6216\u7b49\u4e8e\u8868\u8fbe\u5f0f B \uff082000)<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void IfElseExample()\n{\n    \/\/ This is illegal, given that Length returns an int, not a bool.\n    \/\/ \u8fd9\u662f\u975e\u6cd5\u7684\uff0c\u56e0\u4e3a Length \u8fd4\u56de\u7684\u662f int\uff0c\u800c\u4e0d\u662f\u5e03\u5c14\u503c\u3002\n    string stringData = &quot;My textual data&quot;;\n    if (stringData.Length)\n    {\n        Console.WriteLine(&quot;string is greater than 0 characters&quot;);\n    }\n    else\n    {\n        Console.WriteLine(&quot;string is not greater than 0 characters&quot;);\n    }\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>If you want to use the String.Length property to determine truth or falsity, you need to modify your conditional expression to resolve to a Boolean.<br \/>\n\u5982\u679c\u8981\u4f7f\u7528 String.Length \u5c5e\u6027\u6765\u786e\u5b9a\u771f\u5047\uff0c\u5219\u9700\u8981\u4fee\u6539\u6761\u4ef6\u8868\u8fbe\u5f0f\u4ee5\u89e3\u6790\u4e3a\u5e03\u5c14\u503c\u3002<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Legal, as this resolves to either true or false.\n\/\/ \u5408\u6cd5\uff0c\u56e0\u4e3a\u8fd9\u89e3\u6790\u4e3a\u771f\u6216\u5047\u3002\nif(stringData.Length &gt; 0)\n{\n    Console.WriteLine(&quot;string is greater than 0 characters&quot;);\n}\n<\/pre>\n<\/p>\n<h3>Using if\/else with Pattern Matching (New 7.0)<\/h3>\n<p>\u5c06 if\/else \u4e0e\u6a21\u5f0f\u5339\u914d\u7ed3\u5408\u4f7f\u7528\uff08\u65b0\u7248 7.0\uff09<\/p>\n<p>New in C# 7.0, pattern matching is allowed in if\/else statements. Pattern matching allows code to inspect an object for certain traits and properties and make decisions based on the (non)existence of those properties and traits. Do not worry if you are new to object-oriented programming; the previous sentence will be explained in great detail in later chapters. Just know (for now) that you can check the type of an object using the is keyword, assign that object to a variable if the pattern matches, and then use that variable.<br \/>\nC# 7.0 \u4e2d\u7684\u65b0\u589e\u529f\u80fd\u662f if\/else \u8bed\u53e5\u4e2d\u5141\u8bb8\u6a21\u5f0f\u5339\u914d\u3002\u6a21\u5f0f\u5339\u914d\u5141\u8bb8\u4ee3\u7801\u68c0\u67e5\u5bf9\u8c61\u7684\u67d0\u4e9b\u7279\u5f81\u548c\u5c5e\u6027\uff0c\u5e76\u6839\u636e\u8fd9\u4e9b\u5c5e\u6027\u548c\u7279\u5f81\u7684\uff08\u4e0d\u5b58\u5728\uff09\u505a\u51fa\u51b3\u7b56\u3002\u5982\u679c\u60a8\u4e0d\u719f\u6089\u9762\u5411\u5bf9\u8c61\u7f16\u7a0b\uff0c\u8bf7\u4e0d\u8981\u62c5\u5fc3;\u524d\u4e00\u53e5\u5c06\u5728\u540e\u9762\u7684\u7ae0\u8282\u4e2d\u8be6\u7ec6\u89e3\u91ca\u3002\u53ea\u8981\u77e5\u9053\uff08\u73b0\u5728\uff09\u60a8\u53ef\u4ee5\u4f7f\u7528is\u5173\u952e\u5b57\u68c0\u67e5\u5bf9\u8c61\u7684\u7c7b\u578b\uff0c\u5982\u679c\u6a21\u5f0f\u5339\u914d\uff0c\u5219\u5c06\u8be5\u5bf9\u8c61\u5206\u914d\u7ed9\u53d8\u91cf\uff0c\u7136\u540e\u4f7f\u7528\u8be5\u53d8\u91cf\u3002<\/p>\n<p>The IfElsePatternMatching method examines two object variables and determines if they are a string or an int and then prints the results to the console:<br \/>\nIfElsePatternMatch \u65b9\u6cd5\u68c0\u67e5\u4e24\u4e2a\u5bf9\u8c61\u53d8\u91cf\u5e76\u786e\u5b9a\u5b83\u4eec\u662f\u5426\u4e3a\u5b57\u7b26\u4e32\u6216 int\uff0c\u7136\u540e\u5c06\u7ed3\u679c\u6253\u5370\u5230\u63a7\u5236\u53f0\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void IfElsePatternMatching()\n{\n    Console.WriteLine(&quot;===If Else Pattern Matching ===&quot;);\n    object testItem1 = 123;\n    object testItem2 = &quot;Hello&quot;;\n    if (testItem1 is string myStringValue1)\n    {\n        Console.WriteLine($&quot;{myStringValue1} is a string&quot;);\n    }\n    if (testItem1 is int myValue1)\n    {\n        Console.WriteLine($&quot;{myValue1} is an int&quot;);\n    }\n    if (testItem2 is string myStringValue2)\n    {\n        Console.WriteLine($&quot;{myStringValue2} is a string&quot;);\n    }\n    if (testItem2 is int myValue2)\n    {\n        Console.WriteLine($&quot;{myValue2} is an int&quot;);\n    }\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<h2>Making Pattern Matching Improvements (New 9.0)<\/h2>\n<p>\u8fdb\u884c\u6a21\u5f0f\u5339\u914d\u6539\u8fdb\uff08\u65b0 9.0\uff09<\/p>\n<p>C# 9.0 has introduced a host of improvements to pattern matching, as shown in Table 3-9.<br \/>\nC# 9.0 \u5bf9\u6a21\u5f0f\u5339\u914d\u8fdb\u884c\u4e86\u5927\u91cf\u6539\u8fdb\uff0c\u5982\u8868 3-9 \u6240\u793a\u3002<\/p>\n<p>Table 3-9. Pattern Matching Improvements<br \/>\n\u8868 3-9. \u6a21\u5f0f\u5339\u914d\u6539\u8fdb<\/p>\n<table>\n<tr>\n<td>Pattern<\/td>\n<td>Meaning in Life<\/td>\n<\/tr>\n<tr>\n<td>Type patterns<\/td>\n<td>Checks if a variable is a type<br \/>\n        \u68c0\u67e5\u53d8\u91cf\u662f\u5426\u4e3a\u7c7b\u578b<\/td>\n<\/tr>\n<tr>\n<td>Parenthesized patterns<\/td>\n<td>Enforces or emphasizes the precedence of pattern combinations<br \/>\n        \u5f3a\u5236\u6216\u5f3a\u8c03\u6a21\u5f0f\u7ec4\u5408\u7684\u4f18\u5148\u7ea7<\/td>\n<\/tr>\n<tr>\n<td>Conjuctive (and) patterns<\/td>\n<td>Requires both patterns to match<br \/>\n        \u8981\u6c42\u4e24\u79cd\u6a21\u5f0f\u5339\u914d<\/td>\n<\/tr>\n<tr>\n<td>Disjunctive (or) patterns<\/td>\n<td>Requires either pattern to match<br \/>\n        \u8981\u6c42\u4efb\u4e00\u6a21\u5f0f\u5339\u914d<\/td>\n<\/tr>\n<tr>\n<td>Negated (not) patterns<\/td>\n<td>Requires a pattern does not match<br \/>\n        \u8981\u6c42\u6a21\u5f0f\u4e0d\u5339\u914d<\/td>\n<\/tr>\n<tr>\n<td>Relational patterns<\/td>\n<td>Requires input to be less than, less than or equal, greater than, or greater than or equal<br \/>\n        \u8981\u6c42\u8f93\u5165\u5c0f\u4e8e\u3001\u5c0f\u4e8e\u6216\u7b49\u4e8e\u3001\u5927\u4e8e\u6216\u5927\u4e8e\u6216\u7b49\u4e8e<\/td>\n<\/tr>\n<tr>\n<td>Pattern combinator<\/td>\n<td>Allows multiple patterns to be used together.\u5141\u8bb8\u591a\u4e2a\u6a21\u5f0f\u4e00\u8d77\u4f7f\u7528\u3002<\/td>\n<\/tr>\n<\/table>\n<p>The updated IfElsePatternMatchingUpdatedInCSharp9() shows these new patterns in action:<br \/>\n\u66f4\u65b0\u7684 IfElsePatternMatchingUpdateInCSharp9\uff08\uff09 \u663e\u793a\u4e86\u8fd9\u4e9b\u65b0\u6a21\u5f0f\u7684\u5b9e\u9645\u5e94\u7528\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void IfElsePatternMatchingUpdatedInCSharp9()\n{\n    Console.WriteLine(&quot;======= C# 9 If Else Pattern Matching Improvements =======&quot;);\n    object testItem1 = 123;\n    Type t = typeof(string);\n    char c = 'f';\n    \/\/ Type patterns\n    \/\/ \u952e\u5165\u6a21\u5f0f\n    if (t is Type)\n    {\n        Console.WriteLine($&quot;{t} is a Type&quot;);\n    }\n    \/\/ Relational, Conjuctive, and Disjunctive patterns\n    \/\/ \u5173\u7cfb\u3001\u5171\u8f6d\u548c\u6790\u53d6\u6a21\u5f0f\uff08\u4ec0\u4e48\u9b3c\uff1f\uff09\n    if (c is &gt;= 'a' and &lt;= 'z' or &gt;= 'A' and &lt;= 'Z')\n    {\n        Console.WriteLine($&quot;{c} is a character&quot;);\n    };\n    \/\/ Parenthesized patterns\n    \/\/ \u62ec\u53f7\u56fe\u6848\n    if (c is (&gt;= 'a' and &lt;= 'z') or (&gt;= 'A' and &lt;= 'Z') or '.' or ',')\n    {\n        Console.WriteLine($&quot;{c} is a character or separator&quot;);\n    };\n    \/\/ Negative patterns\n    \/\/ \u8d1f\u9762\u6a21\u5f0f\n    if (testItem1 is not string)\n    {\n        Console.WriteLine($&quot;{testItem1} is not a string&quot;);\n    }\n    if (testItem1 is not null)\n    {\n        Console.WriteLine($&quot;{testItem1} is not null&quot;);\n    }\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<h2>Using the Conditional Operator (Updated 7.2, 9.0)<\/h2>\n<p>\u4f7f\u7528\u6761\u4ef6\u8fd0\u7b97\u7b26\uff087.2\u30019.0 \u66f4\u65b0\uff09<\/p>\n<p>The conditional operator (?:), also known as the ternary conditional operator, is a shorthand method of writing a simple if\/else statement. The syntax works like this:<br \/>\n\u6761\u4ef6\u8fd0\u7b97\u7b26 \uff08\uff1f\uff1a\uff09\uff0c\u4e5f\u79f0\u4e3a\u4e09\u5143\u6761\u4ef6\u8fd0\u7b97\u7b26\uff0c\u662f\u7f16\u5199\u7b80\u5355 if\/else \u8bed\u53e5\u7684\u7b80\u5199\u65b9\u6cd5\u3002\u8bed\u6cd5\u7684\u5de5\u4f5c\u65b9\u5f0f\u5982\u4e0b\uff1a<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ncondition ? first_expression : second_expression;\n<\/pre>\n<\/p>\n<p>The condition is the conditional test (the if part of the if\/else statement). If the test passes, then the code immediately after the question mark (?) is executed. If the test does not evaluate to true, the code after the colon (the else part of the if\/else statement) is executed. The previous code example can be written using the conditional operator like this:<br \/>\n\u6761\u4ef6\u662f\u6761\u4ef6\u6d4b\u8bd5\uff08if\/else \u8bed\u53e5\u7684 if \u90e8\u5206\uff09\u3002\u5982\u679c\u6d4b\u8bd5\u901a\u8fc7\uff0c\u5219\u7d27\u8ddf\u5728\u95ee\u53f7 \uff08\uff1f\uff09 \u4e4b\u540e\u7684\u4ee3\u7801\u5c06\u6267\u884c\u3002\u5982\u679c\u6d4b\u8bd5\u7684\u8ba1\u7b97\u7ed3\u679c\u672a\u4e3a true\uff0c\u5219\u6267\u884c\u5192\u53f7\uff08if\/else \u8bed\u53e5\u7684 else \u90e8\u5206\uff09\u540e\u9762\u7684\u4ee3\u7801\u3002\u524d\u9762\u7684\u4ee3\u7801\u793a\u4f8b\u53ef\u4ee5\u4f7f\u7528\u6761\u4ef6\u8fd0\u7b97\u7b26\u7f16\u5199\uff0c\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void ExecuteIfElseUsingConditionalOperator()\n{\n    string stringData = &quot;My textual data&quot;;\n    Console.WriteLine(stringData.Length &gt; 0\n    ? &quot;string is greater than 0 characters&quot;\n    : &quot;string is not greater than 0 characters&quot;);\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>There are some restrictions to the conditional operator. First, both types of first_expression and second_expression must have implicit conversions to from one to another, or, new in C# 9.0, each must have an implicit conversion to a target type. Second, the conditional operator can be used only in assignment statements. The following code will result in the compiler error \u201cOnly assignment, call, increment, decrement, and new object expressions can be used as a statement\u201d:<br \/>\n\u5bf9\u6761\u4ef6\u8fd0\u7b97\u7b26\u6709\u4e00\u4e9b\u9650\u5236\u3002\u9996\u5148\uff0c\u4e24\u79cd\u7c7b\u578b\u7684first_expression\u548csecond_expression\u90fd\u5fc5\u987b\u5177\u6709\u4ece\u4e00\u79cd\u5230\u53e6\u4e00\u79cd\u7684\u9690\u5f0f\u8f6c\u6362\uff0c\u6216\u8005\uff0c\u5728 C# 9.0 \u4e2d\uff0c\u6bcf\u79cd\u7c7b\u578b\u90fd\u5fc5\u987b\u5177\u6709\u5230\u76ee\u6807\u7c7b\u578b\u7684\u9690\u5f0f\u8f6c\u6362\u3002\u5176\u6b21\uff0c\u6761\u4ef6\u8fd0\u7b97\u7b26\u53ea\u80fd\u5728\u8d4b\u503c\u8bed\u53e5\u4e2d\u4f7f\u7528\u3002\u4ee5\u4e0b\u4ee3\u7801\u5c06\u5bfc\u81f4\u7f16\u8bd1\u5668\u9519\u8bef\u201c\u53ea\u6709\u8d4b\u503c\u3001\u8c03\u7528\u3001\u9012\u589e\u3001\u9012\u51cf\u548c\u65b0\u5bf9\u8c61\u8868\u8fbe\u5f0f\u53ef\u4ee5\u7528\u4f5c\u8bed\u53e5\u201d\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstringData.Length &gt; 0\n? Console.WriteLine(&quot;string is greater than 0 characters&quot;)\n: Console.WriteLine(&quot;string is not greater than 0 characters&quot;);\n<\/pre>\n<\/p>\n<p>New in C# 7.2, the conditional operator can be used to return a reference to the result of the condition.Take the following example, which uses two forms of the conditional operator by ref:<br \/>\n\u6761\u4ef6\u8fd0\u7b97\u7b26\u662f C# 7.2 \u4e2d\u7684\u65b0\u589e\u529f\u80fd\uff0c\u53ef\u7528\u4e8e\u8fd4\u56de\u5bf9\u6761\u4ef6\u7ed3\u679c\u7684\u5f15\u7528\u3002\u4ee5\u4ee5\u4e0b\u793a\u4f8b\u4e3a\u4f8b\uff0c\u8be5\u793a\u4f8b\u901a\u8fc7 ref \u4f7f\u7528\u4e24\u79cd\u5f62\u5f0f\u7684\u6761\u4ef6\u8fd0\u7b97\u7b26\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void ConditionalRefExample()\n{\n    var smallArray = new int&#x5B;] { 1, 2, 3, 4, 5 };\n    var largeArray = new int&#x5B;] { 10, 20, 30, 40, 50 };\n    int index = 7;\n    ref int refValue = ref ((index &lt; 5)\n    ? ref smallArray&#x5B;index]\n    : ref largeArray&#x5B;index - 5]);\n    refValue = 0; \n    index = 2;\n    ((index &lt; 5)\n    ? ref smallArray&#x5B;index]\n    : ref largeArray&#x5B;index - 5]) = 100;\n    Console.WriteLine(string.Join(&quot; &quot;, smallArray));\n    Console.WriteLine(string.Join(&quot; &quot;, largeArray));\n}\n<\/pre>\n<\/p>\n<p>If you are not familiar with the ref keyword, do not worry too much at this point, as it will be covered in depth in the next chapter. To sum up, the first example returns a reference to the array location checked with the condition and assigns the refValue variable to that reference. Think of the reference conceptually as a point to the location in the array and not the actual value of the position of the array. This allows for changing of the array\u2019s value in that position directly by changing the value assigned to the variable. The result of setting the value of the refValue variable to zero changes the second array\u2019s values to 10,20,0,40,50. The second example updates the first array\u2019s second value to 100, resulting in 1,2,100,4,5.<br \/>\n\u5982\u679c\u60a8\u4e0d\u719f\u6089 ref \u5173\u952e\u5b57\uff0c\u6b64\u65f6\u4e0d\u8981\u592a\u62c5\u5fc3\uff0c\u56e0\u4e3a\u5b83\u5c06\u5728\u4e0b\u4e00\u7ae0\u4e2d\u6df1\u5165\u4ecb\u7ecd\u3002\u603b\u800c\u8a00\u4e4b\uff0c\u7b2c\u4e00\u4e2a\u793a\u4f8b\u8fd4\u56de\u5bf9\u4f7f\u7528\u8be5\u6761\u4ef6\u68c0\u67e5\u7684\u6570\u7ec4\u4f4d\u7f6e\u7684\u5f15\u7528\uff0c\u5e76\u5c06 refValue \u53d8\u91cf\u5206\u914d\u7ed9\u8be5\u5f15\u7528\u3002\u4ece\u6982\u5ff5\u4e0a\u8bb2\uff0c\u5c06\u5f15\u7528\u89c6\u4e3a\u6570\u7ec4\u4e2d\u4f4d\u7f6e\u7684\u70b9\uff0c\u800c\u4e0d\u662f\u6570\u7ec4\u4f4d\u7f6e\u7684\u5b9e\u9645\u503c\u3002\u8fd9\u5141\u8bb8\u901a\u8fc7\u66f4\u6539\u5206\u914d\u7ed9\u53d8\u91cf\u7684\u503c\u6765\u76f4\u63a5\u66f4\u6539\u8be5\u4f4d\u7f6e\u7684\u6570\u7ec4\u503c\u3002\u8fd9\u5c06 refValue \u53d8\u91cf\u7684\u503c\u8bbe\u7f6e\u4e3a\u96f6\u7684\u7ed3\u679c\u4f1a\u5c06\u7b2c\u4e8c\u4e2a\u6570\u7ec4\u7684\u503c\u66f4\u6539\u4e3a 10,20,0,40,50\u3002\u7b2c\u4e8c\u4e2a\u793a\u4f8b\u5c06\u7b2c\u4e00\u4e2a\u6570\u7ec4\u7684\u7b2c\u4e8c\u4e2a\u503c\u66f4\u65b0\u4e3a 100\uff0c\u7ed3\u679c\u4e3a 1,2,100,4,5\u3002<\/p>\n<h2>Using Logical Operators<\/h2>\n<p>\u4f7f\u7528\u903b\u8f91\u8fd0\u7b97\u7b26<\/p>\n<p>An if statement may be composed of complex expressions as well and can contain else statements to perform more complex testing. The syntax is identical to C (and C++) and Java. To build complex expressions, C# offers an expected set of logical operators, as shown in Table 3-10.<br \/>\nif \u8bed\u53e5\u4e5f\u53ef\u4ee5\u7531\u590d\u6742\u7684\u8868\u8fbe\u5f0f\u7ec4\u6210\uff0c\u5e76\u4e14\u53ef\u4ee5\u5305\u542b else \u8bed\u53e5\u6765\u6267\u884c\u66f4\u590d\u6742\u7684\u6d4b\u8bd5\u3002\u8bed\u6cd5\u4e0eC\uff08\u548cC++\uff09\u548cJava\u76f8\u540c\u3002\u4e3a\u4e86\u751f\u6210\u590d\u6742\u7684\u8868\u8fbe\u5f0f\uff0cC# \u63d0\u4f9b\u4e86\u4e00\u7ec4\u9884\u671f\u7684\u903b\u8f91\u8fd0\u7b97\u7b26\uff0c\u5982\u8868 3-10 \u6240\u793a\u3002<\/p>\n<p>Table 3-10. C# Logical Operators<br \/>\n\u8868 3-10. C# \u903b\u8f91\u8fd0\u7b97\u7b26<\/p>\n<table>\n<tr>\n<td>Operator<\/td>\n<td>Example<\/td>\n<td>Meaning in Life<\/td>\n<\/tr>\n<tr>\n<td>&amp;&amp;<\/td>\n<td>if(age == 30 &amp;&amp; name == &quot;Fred&quot;)<\/td>\n<td>AND operator. Returns true if all expressions are true.<br \/>\n        \u548c\u8fd0\u7b97\u7b26\u3002\u5982\u679c\u6240\u6709\u8868\u8fbe\u5f0f\u90fd\u4e3a true\uff0c\u5219\u8fd4\u56de true\u3002<\/td>\n<\/tr>\n<tr>\n<td>||<\/td>\n<td>if(age == 30 || name == &quot;Fred&quot;)<\/td>\n<td>OR operator. Returns true if at least one expression is true.<br \/>\n        OR \u8fd0\u7b97\u7b26\u3002\u5982\u679c\u81f3\u5c11\u6709\u4e00\u4e2a\u8868\u8fbe\u5f0f\u4e3a true\uff0c\u5219\u8fd4\u56de true\u3002<\/td>\n<\/tr>\n<tr>\n<td>!<\/td>\n<td>if(!myBool)<\/td>\n<td>NOT operator. Returns true if false, or false if true.<br \/>\n        \u4e0d\u662f\u8fd0\u7b97\u7b26\u3002\u5982\u679c\u4e3a\u5047\uff0c\u5219\u8fd4\u56de true\uff0c\u5982\u679c\u4e3a\u771f\uff0c\u5219\u8fd4\u56de false\u3002<\/td>\n<\/tr>\n<\/table>\n<blockquote><p>\n\u25a0 Note the &amp;&amp; and || operators both \u201cshort-circuit\u201d when necessary. this means that after a complex expression has been determined to be false, the remaining subexpressions will not be checked. if you require all expressions to be tested regardless, you can use the related &amp; and | operators.<br \/>\n\u8bf7\u6ce8\u610f &amp;&amp; \u548c || \u5fc5\u8981\u65f6\uff0c\u64cd\u4f5c\u5458\u90fd\u4f1a\u201c\u77ed\u8def\u201d\u3002\u8fd9\u610f\u5473\u7740\u5728\u786e\u5b9a\u590d\u6742\u8868\u8fbe\u5f0f\u4e3a false \u540e\uff0c\u5c06\u4e0d\u68c0\u67e5\u5176\u4f59\u5b50\u8868\u8fbe\u5f0f\u3002\u5982\u679c\u4f60\u8981\u6c42\u65e0\u8bba\u5982\u4f55\u90fd\u8981\u6d4b\u8bd5\u6240\u6709\u8868\u8fbe\u5f0f\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528\u76f8\u5173\u7684 &amp;\u548c | \u8fd0\u8425\u5546\u3002\n<\/p><\/blockquote>\n<h3>Using the switch Statement<\/h3>\n<p>\u4f7f\u7528\u5f00\u5173\u8bed\u53e5<\/p>\n<p>The other simple selection construct offered by C# is the switch statement. As in other C-based languages, the switch statement allows you to handle program flow based on a predefined set of choices. For example, the following logic prints a specific string message based on one of two possible selections (the default case handles an invalid selection):<br \/>\nC# \u63d0\u4f9b\u7684\u53e6\u4e00\u4e2a\u7b80\u5355\u9009\u62e9\u6784\u9020\u662f switch \u8bed\u53e5\u3002\u4e0e\u5176\u4ed6\u57fa\u4e8e C \u7684\u8bed\u8a00\u4e00\u6837\uff0cswitch \u8bed\u53e5\u5141\u8bb8\u60a8\u57fa\u4e8e\u4e00\u7ec4\u9884\u5b9a\u4e49\u7684\u9009\u62e9\u6765\u5904\u7406\u7a0b\u5e8f\u6d41\u3002\u4f8b\u5982\uff0c\u4ee5\u4e0b\u903b\u8f91\u6839\u636e\u4e24\u4e2a\u53ef\u80fd\u7684\u9009\u62e9\u4e4b\u4e00\u6253\u5370\u7279\u5b9a\u7684\u5b57\u7b26\u4e32\u6d88\u606f\uff08\u9ed8\u8ba4\u60c5\u51b5\u5904\u7406\u65e0\u6548\u9009\u62e9\uff09\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Switch on a numerical value.\n\/\/ \u6570\u503c\u5f00\u5173\u3002\nstatic void SwitchExample()\n{\n    Console.WriteLine(&quot;1 &#x5B;C#], 2 &#x5B;VB]&quot;);\n    Console.Write(&quot;Please pick your language preference: &quot;);\n    string langChoice = Console.ReadLine();\n    int n = int.Parse(langChoice);\n    switch (n)\n    {\n        case 1:\n            Console.WriteLine(&quot;Good choice, C# is a fine language.&quot;);\n            break;\n        case 2:\n            Console.WriteLine(&quot;VB: OOP, multithreading, and more!&quot;);\n            break;\n        default:\n            Console.WriteLine(&quot;Well...good luck with that!&quot;);\n            break;\n    }\n}\n<\/pre>\n<\/p>\n<blockquote><p>\n\u25a0 Note C# demands that each case (including default) that contains executable statements have a terminating return, break, or goto to avoid falling through to the next statement.<br \/>\n\u6ce8\u610f C# \u8981\u6c42\u5305\u542b\u53ef\u6267\u884c\u8bed\u53e5\u7684\u6bcf\u4e2a\u4e8b\u4f8b\uff08\u5305\u62ec\u9ed8\u8ba4\u503c\uff09\u90fd\u5177\u6709\u7ec8\u6b62\u56de\u8f66\u3001\u4e2d\u65ad\u6216 goto\uff0c\u4ee5\u907f\u514d\u843d\u5165\u4e0b\u4e00\u6761\u8bed\u53e5\u3002\n<\/p><\/blockquote>\n<p>One nice feature of the C# switch statement is that you can evaluate string data in addition to numeric data. In fact, all versions of C# can evaluate char, string, bool, int, long, and enum data types. As you will see in the next section, C# 7 adds additional capabilities. Here is an updated switch statement that evaluates a string variable:<br \/>\nC# switch \u8bed\u53e5\u7684\u4e00\u4e2a\u5f88\u597d\u7684\u529f\u80fd\u662f\uff0c\u9664\u4e86\u6570\u503c\u6570\u636e\u4e4b\u5916\uff0c\u8fd8\u53ef\u4ee5\u8ba1\u7b97\u5b57\u7b26\u4e32\u6570\u636e\u3002\u4e8b\u5b9e\u4e0a\uff0c\u6240\u6709\u7248\u672c\u7684 C# \u90fd\u53ef\u4ee5\u8ba1\u7b97\u5b57\u7b26\u3001\u5b57\u7b26\u4e32\u3001\u5e03\u5c14\u503c\u3001\u6574\u6570\u3001\u957f\u6574\u578b\u548c\u679a\u4e3e\u6570\u636e\u7c7b\u578b\u3002\u6b63\u5982\u60a8\u5c06\u5728\u4e0b\u4e00\u8282\u4e2d\u770b\u5230\u7684\uff0cC# 7 \u6dfb\u52a0\u4e86\u5176\u4ed6\u529f\u80fd\u3002\u4e0b\u9762\u662f\u4e00\u4e2a\u66f4\u65b0\u7684 switch \u8bed\u53e5\uff0c\u7528\u4e8e\u8ba1\u7b97\u5b57\u7b26\u4e32\u53d8\u91cf\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void SwitchOnStringExample()\n{\n    Console.WriteLine(&quot;C# or VB&quot;);\n    Console.Write(&quot;Please pick your language preference: &quot;);\n    string langChoice = Console.ReadLine();\n    switch (langChoice.ToUpper())\n    {\n        case &quot;C#&quot;:\n            Console.WriteLine(&quot;Good choice, C# is a fine language.&quot;);\n            break;\n        case &quot;VB&quot;:\n            Console.WriteLine(&quot;VB: OOP, multithreading and more!&quot;);\n            break;\n        default:\n            Console.WriteLine(&quot;Well...good luck with that!&quot;);\n            break;\n    }\n}\n<\/pre>\n<\/p>\n<p>It is also possible to switch on an enumeration data type. As you will see in Chapter 4, the C# enum keyword allows you to define a custom set of name-value pairs. To whet your appetite, consider the following final helper function, which performs a switch test on the System.DayOfWeek enum. You will notice some syntax I have not yet examined, but focus on the issue of switching over the enum itself; the missing pieces will be filled in over the chapters to come.<br \/>\n\u4e5f\u53ef\u4ee5\u6253\u5f00\u679a\u4e3e\u6570\u636e\u7c7b\u578b\u3002\u6b63\u5982\u60a8\u5c06\u5728\u7b2c 4 \u7ae0\u4e2d\u770b\u5230\u7684\uff0cC# \u679a\u4e3e\u5173\u952e\u5b57\u5141\u8bb8\u60a8\u5b9a\u4e49\u4e00\u7ec4\u81ea\u5b9a\u4e49\u7684\u540d\u79f0\/\u503c\u5bf9\u3002\u4e3a\u4e86\u6fc0\u53d1\u60a8\u7684\u80c3\u53e3\uff0c\u8bf7\u8003\u8651\u4ee5\u4e0b\u6700\u540e\u4e00\u4e2a\u5e2e\u52a9\u7a0b\u5e8f\u51fd\u6570\uff0c\u8be5\u51fd\u6570\u5728 System.DayOfWeek \u679a\u4e3e\u4e0a\u6267\u884c\u5f00\u5173\u6d4b\u8bd5\u3002\u4f60\u4f1a\u6ce8\u610f\u5230\u4e00\u4e9b\u6211\u8fd8\u6ca1\u6709\u68c0\u67e5\u7684\u8bed\u6cd5\uff0c\u4f46\u91cd\u70b9\u662f\u5207\u6362\u679a\u4e3e\u672c\u8eab\u7684\u95ee\u9898;\u7f3a\u5931\u7684\u90e8\u5206\u5c06\u5728\u4ee5\u540e\u7684\u7ae0\u8282\u4e2d\u586b\u8865\u3002<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic void SwitchOnEnumExample()\n{\n    Console.Write(&quot;Enter your favorite day of the week: &quot;);\n    DayOfWeek favDay;\n    try\n    {\n        favDay = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), Console.ReadLine());\n    }\n    catch (Exception)\n    {\n        Console.WriteLine(&quot;Bad input!&quot;);\n        return;\n    }\n    switch (favDay)\n    {\n        case DayOfWeek.Sunday:\n            Console.WriteLine(&quot;Football!!&quot;);\n            break;\n        case DayOfWeek.Monday:\n            Console.WriteLine(&quot;Another day, another dollar&quot;);\n            break;\n        case DayOfWeek.Tuesday:\n            Console.WriteLine(&quot;At least it is not Monday&quot;);\n            break;\n        case DayOfWeek.Wednesday:\n            Console.WriteLine(&quot;A fine day.&quot;);\n            break;\n        case DayOfWeek.Thursday:\n            Console.WriteLine(&quot;Almost Friday...&quot;);\n            break;\n        case DayOfWeek.Friday:\n            Console.WriteLine(&quot;Yes, Friday rules!&quot;);\n            break;\n        case DayOfWeek.Saturday:\n            Console.WriteLine(&quot;Great day indeed.&quot;);\n            break;\n    }\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>Falling through from one case statement to another case statement is not allowed, but what if multiple case statements should produce the same result? Fortunately, they can be combined, as the following code snippet demonstrates:<br \/>\n\u4e0d\u5141\u8bb8\u4ece\u4e00\u4e2a\u6848\u4f8b\u9648\u8ff0\u8dcc\u5230\u53e6\u4e00\u4e2a\u6848\u4f8b\u9648\u8ff0\uff0c\u4f46\u5982\u679c\u591a\u4e2a\u6848\u4f8b\u9648\u8ff0\u5e94\u8be5\u4ea7\u751f\u76f8\u540c\u7684\u7ed3\u679c\u600e\u4e48\u529e\uff1f\u5e78\u8fd0\u7684\u662f\uff0c\u5b83\u4eec\u53ef\u4ee5\u7ec4\u5408\u5728\u4e00\u8d77\uff0c\u5982\u4ee5\u4e0b\u4ee3\u7801\u7247\u6bb5\u6240\u793a\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \ncase DayOfWeek.Saturday:\ncase DayOfWeek.Sunday:\n    Console.WriteLine(&quot;It\u2019s the weekend!&quot;); \n    break;\n<\/pre>\n<\/p>\n<p>If any code were included between the case statements, the compiler would throw an error. As long as they are consecutive statements, as shown earlier, case statements can be combined to share common code.<br \/>\n\u5982\u679c\u5728 case \u8bed\u53e5\u4e4b\u95f4\u5305\u542b\u4efb\u4f55\u4ee3\u7801\uff0c\u7f16\u8bd1\u5668\u5c06\u5f15\u53d1\u9519\u8bef\u3002\u53ea\u8981\u5b83\u4eec\u662f\u8fde\u7eed\u8bed\u53e5\uff0c\u5982\u524d\u6240\u8ff0\uff0c\u5c31\u53ef\u4ee5\u7ec4\u5408 case \u8bed\u53e5\u4ee5\u5171\u4eab\u516c\u5171\u4ee3\u7801\u3002<\/p>\n<p>In addition to the return and break statements shown in the previous code samples, the switch statement also supports using a goto to exit a case condition and execute another case statement. While this is supported, it is pretty universally thought of as an anti-pattern and not generally used. Here is an example of using the goto statement in a switch block:<br \/>\n\u9664\u4e86\u524d\u9762\u7684\u4ee3\u7801\u793a\u4f8b\u4e2d\u663e\u793a\u7684\u8fd4\u56de\u548c\u4e2d\u65ad\u8bed\u53e5\u5916\uff0cswitch \u8bed\u53e5\u8fd8\u652f\u6301\u4f7f\u7528 goto \u9000\u51fa\u6848\u4f8b\u6761\u4ef6\u5e76\u6267\u884c\u53e6\u4e00\u4e2a\u6848\u4f8b\u8bed\u53e5\u3002\u867d\u7136\u8fd9\u5f97\u5230\u4e86\u652f\u6301\uff0c\u4f46\u5b83\u88ab\u666e\u904d\u8ba4\u4e3a\u662f\u4e00\u79cd\u53cd\u6a21\u5f0f\uff0c\u901a\u5e38\u4e0d\u4f7f\u7528\u3002\u4e0b\u9762\u662f\u5728\u5f00\u5173\u5757\u4e2d\u4f7f\u7528 goto \u8bed\u53e5\u7684\u793a\u4f8b\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \nstatic void SwitchWithGoto()\n{\n    var foo = 5;\n    switch (foo)\n    {\n        case 1:\n            \/\/ do something\n            \/\/ \u505a\u70b9\u4ec0\u4e48\n            goto case 2;\n        case 2:\n            \/\/ do something else\n            \/\/ \u505a\u70b9\u522b\u7684\u4ec0\u4e48\n            break;\n        case 3:\n            \/\/ yet another action\n            \/\/ \u6709\u4e00\u4e2a\u52a8\u4f5c\n            goto default;\n        default:\n            \/\/ default action\n            \/\/ \u9ed8\u8ba4\u52a8\u4f5c\n            break;\n    }\n}\n<\/pre>\n<\/p>\n<h2>Performing switch Statement Pattern Matching (New 7.0, Updated 9.0)<\/h2>\n<p>\u6267\u884c\u4ea4\u6362\u673a\u8bed\u53e5\u6a21\u5f0f\u5339\u914d\uff08\u65b0\u7248 7.0\uff0c\u66f4\u65b0\u7684 9.0\uff09<\/p>\n<p>Prior to C# 7, match expressions in switch statements were limited to comparing a variable to constant values, sometimes referred to as the constant pattern. In C# 7, switch statements can also employ the type pattern, where case statements can evaluate the type of the variable being checked and case expressions are no longer limited to constant values. The rule that each case statement must be terminated with a return or break still applies; however, goto statements are not supported using the type pattern.<br \/>\n\u5728 C# 7 \u4e4b\u524d\uff0cswitch \u8bed\u53e5\u4e2d\u7684\u5339\u914d\u8868\u8fbe\u5f0f\u4ec5\u9650\u4e8e\u5c06\u53d8\u91cf\u4e0e\u5e38\u91cf\u503c\u8fdb\u884c\u6bd4\u8f83\uff0c\u6709\u65f6\u79f0\u4e3a\u5e38\u91cf\u6a21\u5f0f\u3002\u5728 C# 7 \u4e2d\uff0cswitch \u8bed\u53e5\u8fd8\u53ef\u4ee5\u91c7\u7528\u7c7b\u578b\u6a21\u5f0f\uff0c\u5176\u4e2d case \u8bed\u53e5\u53ef\u4ee5\u8ba1\u7b97\u8981\u68c0\u67e5\u7684\u53d8\u91cf\u7684\u7c7b\u578b\uff0c\u5e76\u4e14 case \u8868\u8fbe\u5f0f\u4e0d\u518d\u5c40\u9650\u4e8e\u5e38\u91cf\u503c\u3002\u6bcf\u4e2a case \u8bed\u53e5\u5fc5\u987b\u4ee5\u8fd4\u56de\u6216\u4e2d\u65ad\u7ec8\u6b62\u7684\u89c4\u5219\u4ecd\u7136\u9002\u7528;\u4f46\u662f\uff0c\u4e0d\u652f\u6301\u4f7f\u7528 GoTo \u8bed\u53e5\u4f7f\u7528\u7c7b\u578b\u6a21\u5f0f\u3002<\/p>\n<blockquote><p>\n\u25a0 Note  if you are new to object-oriented programming, this section might be a little confusing. it will all come together in Chapter 6, when you revisit the new pattern matching features of C# 7 in the context of classes and base classes. For now, just understand that there is a powerful new way to write switch statements.<br \/>\n\u6ce8\u610f \u5982\u679c\u60a8\u4e0d\u719f\u6089\u9762\u5411\u5bf9\u8c61\u7f16\u7a0b\uff0c\u672c\u8282\u53ef\u80fd\u4f1a\u6709\u70b9\u4ee4\u4eba\u56f0\u60d1\u3002 \u5728\u7b2c 6 \u7ae0\u4e2d\uff0c\u5f53\u60a8\u5728\u7c7b\u548c\u57fa\u7c7b\u7684\u4e0a\u4e0b\u6587\u4e2d\u91cd\u65b0\u8bbf\u95ee C# 7 \u7684\u65b0\u6a21\u5f0f\u5339\u914d\u529f\u80fd\u65f6\uff0c\u6240\u6709\u8fd9\u4e9b\u5185\u5bb9\u5c06\u6c47\u96c6\u5728\u4e00\u8d77\u3002\u73b0\u5728\uff0c\u53ea\u8981\u4e86\u89e3\u6709\u4e00\u79cd\u5f3a\u5927\u7684\u65b0\u65b9\u6cd5\u6765\u7f16\u5199 switch \u8bed\u53e5\u3002\n<\/p><\/blockquote>\n<p>Add another method named ExecutePatternMatchingSwitch() and add the following code:<br \/>\n\u6dfb\u52a0\u53e6\u4e00\u4e2a\u540d\u4e3a ExecutePatternMatchingSwitch\uff08\uff09 \u7684\u65b9\u6cd5\uff0c\u5e76\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \nstatic void ExecutePatternMatchingSwitch()\n{\n    Console.WriteLine(&quot;1 &#x5B;Integer (5)], 2 &#x5B;String (\\&quot;Hi\\&quot;)], 3 &#x5B;Decimal (2.5)]&quot;);\n    Console.Write(&quot;Please choose an option: &quot;);\n    string userChoice = Console.ReadLine();\n    object choice;\n    \/\/ This is a standard constant pattern switch statement to set up the example\n    \/\/ \u8fd9\u662f\u4e00\u4e2a\u6807\u51c6\u7684\u5e38\u91cf\u6a21\u5f0f\u5f00\u5173\u8bed\u53e5\uff0c\u7528\u4e8e\u8bbe\u7f6e\u793a\u4f8b\u5f00\u5173\n    switch (userChoice)\n    {\n        case &quot;1&quot;:\n            choice = 5;\n            break;\n        case &quot;2&quot;:\n            choice = &quot;Hi&quot;;\n            break;\n        case &quot;3&quot;:\n            choice = 2.5M;\n            break;\n        default:\n            choice = 5;\n            break;\n    }\n\n    \/\/This is new the pattern matching switch statement\n    \/\/ \u8fd9\u662f\u65b0\u7684\u6a21\u5f0f\u5339\u914d\u5f00\u5173\u8bed\u53e5\n    switch (choice)\n    {\n        case int i:\n            Console.WriteLine(&quot;Your choice is an integer.&quot;);\n            break;\n        case string s:\n            Console.WriteLine(&quot;Your choice is a string.&quot;);\n            break;\n        case decimal d:\n            Console.WriteLine(&quot;Your choice is a decimal.&quot;);\n            break;\n        default:\n            Console.WriteLine(&quot;Your choice is something else&quot;);\n            break;\n    }\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>The first switch statement is using the standard constant pattern and is included merely to set up this (trivial) example. In the second switch statement, the variable is typed as object and, based on the input from the user, can be parsed into an int, string, or decimal data type. Based on the type of the variable, different case statements are matched. In addition to checking the data type, a variable is assigned in each of the case statements (except for the default case). Update the code to the following to use the values in the variables:<br \/>\n\u7b2c\u4e00\u4e2a switch \u8bed\u53e5\u4f7f\u7528\u6807\u51c6\u5e38\u91cf\u6a21\u5f0f\uff0c\u5305\u542b\u5b83\u53ea\u662f\u4e3a\u4e86\u8bbe\u7f6e\u8fd9\u4e2a\uff08\u5fae\u4e0d\u8db3\u9053\u7684\uff09\u793a\u4f8b\u3002\u5728\u7b2c\u4e8c\u4e2a switch \u8bed\u53e5\u4e2d\uff0c\u53d8\u91cf\u88ab\u7c7b\u578b\u5316\u4e3a\u5bf9\u8c61\uff0c\u5e76\u4e14\u6839\u636e\u7528\u6237\u7684\u8f93\u5165\uff0c\u53ef\u4ee5\u89e3\u6790\u4e3a int\u3001string \u6216\u5341\u8fdb\u5236\u6570\u636e\u7c7b\u578b\u3002\u6839\u636e\u53d8\u91cf\u7684\u7c7b\u578b\uff0c\u5339\u914d\u4e0d\u540c\u7684 case \u8bed\u53e5\u3002\u9664\u4e86\u68c0\u67e5\u6570\u636e\u7c7b\u578b\u5916\uff0c\u8fd8\u4f1a\u5728\u6bcf\u4e2a case \u8bed\u53e5\u4e2d\u5206\u914d\u4e00\u4e2a\u53d8\u91cf\uff08\u9ed8\u8ba4\u5927\u5c0f\u5199\u9664\u5916\uff09\u3002\u5c06\u4ee3\u7801\u66f4\u65b0\u4e3a\u4ee5\u4e0b\u5185\u5bb9\u4ee5\u4f7f\u7528\u53d8\u91cf\u4e2d\u7684\u503c\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/This is new the pattern matching switch statement\n\/\/ \u8fd9\u662f\u65b0\u7684\u6a21\u5f0f\u5339\u914d\u5f00\u5173\u8bed\u53e5\nswitch (choice)\n{\n    case int i:\n        Console.WriteLine(&quot;Your choice is an integer {0}.&quot;, i);\n        break;\n    case string s:\n        Console.WriteLine(&quot;Your choice is a string. {0}&quot;, s);\n        break;\n    case decimal d:\n        Console.WriteLine(&quot;Your choice is a decimal. {0}&quot;, d);\n        break;\n    default:\n        Console.WriteLine(&quot;Your choice is something else&quot;);\n        break;\n}\n<\/pre>\n<\/p>\n<p>In addition to evaluating on the type of the match expression, when clauses can be added to the case statements to evaluate conditions on the variable. In this example, in addition to checking the type, the value of the converted type is also checked for a match:<br \/>\n\u9664\u4e86\u8ba1\u7b97\u5339\u914d\u8868\u8fbe\u5f0f\u7684\u7c7b\u578b\u4e4b\u5916\uff0c\u4f55\u65f6\u53ef\u4ee5\u5c06\u5b50\u53e5\u6dfb\u52a0\u5230 case \u8bed\u53e5\u4e2d\u4ee5\u8ba1\u7b97\u53d8\u91cf\u7684\u6761\u4ef6\u3002\u5728\u6b64\u793a\u4f8b\u4e2d\uff0c\u9664\u4e86\u68c0\u67e5\u7c7b\u578b\u5916\uff0c\u8fd8\u68c0\u67e5\u8f6c\u6362\u540e\u7c7b\u578b\u7684\u503c\u662f\u5426\u5339\u914d\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \nstatic void ExecutePatternMatchingSwitchWithWhen()\n{\n    Console.WriteLine(&quot;1 &#x5B;C#], 2 &#x5B;VB]&quot;);\n    Console.Write(&quot;Please pick your language preference: &quot;);\n    object langChoice = Console.ReadLine();\n    var choice = int.TryParse(langChoice.ToString(), out int c) ? c : langChoice;\n    switch (choice)\n    {\n        case int i when i == 2:\n        case string s when s.Equals(&quot;VB&quot;, StringComparison.OrdinalIgnoreCase):\n            Console.WriteLine(&quot;VB: OOP, multithreading, and more!&quot;);\n            break;\n        case int i when i == 1:\n        case string s when s.Equals(&quot;C#&quot;, StringComparison.OrdinalIgnoreCase):\n            Console.WriteLine(&quot;Good choice, C# is a fine language.&quot;);\n            break;\n        default:\n            Console.WriteLine(&quot;Well...good luck with that!&quot;);\n            break;\n    }\n    Console.WriteLine();\n}\n<\/pre>\n<\/p>\n<p>This adds a new dimension to the switch statement as the order of the case statements is now significant. With the constant pattern, each case statement had to be unique. With the type pattern, this is no longer the case. For example, the following code will match every integer in the first case statement and will never execute the second or the third (in fact, the following code will fail to compile):<br \/>\n\u8fd9\u4e3a switch \u8bed\u53e5\u6dfb\u52a0\u4e86\u4e00\u4e2a\u65b0\u7684\u7ef4\u5ea6\uff0c\u56e0\u4e3a case \u8bed\u53e5\u7684\u987a\u5e8f\u73b0\u5728\u5f88\u91cd\u8981\u3002\u5728\u5e38\u91cf\u6a21\u5f0f\u4e0b\uff0c\u6bcf\u4e2a\u6848\u4f8b\u8bed\u53e5\u90fd\u5fc5\u987b\u662f\u552f\u4e00\u7684\u3002\u5bf9\u4e8e\u7c7b\u578b\u6a21\u5f0f\uff0c\u60c5\u51b5\u4e0d\u518d\u5982\u6b64\u3002\u4f8b\u5982\uff0c\u4e0b\u9762\u7684\u4ee3\u7801\u5c06\u5339\u914d\u7b2c\u4e00\u4e2a case \u8bed\u53e5\u4e2d\u7684\u6bcf\u4e2a\u6574\u6570\uff0c\u5e76\u4e14\u6c38\u8fdc\u4e0d\u4f1a\u6267\u884c\u7b2c\u4e8c\u4e2a\u6216\u7b2c\u4e09\u4e2a\uff08\u5b9e\u9645\u4e0a\uff0c\u4e0b\u9762\u7684\u4ee3\u7801\u5c06\u65e0\u6cd5\u7f16\u8bd1\uff09\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \nswitch (choice)\n{\n    case int i:\n        \/\/do something\n        break;\n    case int i when i == 0:\n        \/\/do something\n        break;\n    case int i when i == -1:\n        \/\/ do something\n        break;\n}\n<\/pre>\n<\/p>\n<p>With the initial release of C# 7, there was a small glitch with pattern matching when using generic types.This has been resolved with C# 7.1. Generic types will be covered in Chapter 10. \u5728 C# 7 \u7684\u521d\u59cb\u7248\u672c\u4e2d\uff0c\u4f7f\u7528\u6cdb\u578b\u7c7b\u578b\u65f6\u6a21\u5f0f\u5339\u914d\u51fa\u73b0\u4e86\u4e00\u4e2a\u5c0f\u6545\u969c\u3002\u6b64\u95ee\u9898\u5df2\u5728 C# 7.1 \u4e2d\u5f97\u5230\u89e3\u51b3\u3002\u6cdb\u578b\u7c7b\u578b\u5c06\u5728\u7b2c 10 \u7ae0\u4e2d\u4ecb\u7ecd\u3002<\/p>\n<blockquote><p>\n\u25a0 Note all of the pattern matching improvement in C# 9.0 previously demonstrated are also available for use in switch statements.<br \/>\n\u8bf7\u6ce8\u610f\uff0c\u524d\u9762\u6f14\u793a\u7684 C# 9.0 \u4e2d\u7684\u6240\u6709\u6a21\u5f0f\u5339\u914d\u6539\u8fdb\u4e5f\u53ef\u7528\u4e8e switch \u8bed\u53e5\u3002\n<\/p><\/blockquote>\n<h2>Using switch Expressions (New 8.0)<\/h2>\n<p>\u4f7f\u7528\u5f00\u5173\u8868\u8fbe\u5f0f\uff08\u65b0\u7248 8.0\uff09<\/p>\n<p>New in C# 8 are switch expressions, allowing the assignment of a variable in a concise statement. Consider the C# 7 version of this method that takes in a color and returns the hex value for the color name:<br \/>\nC# 8 \u4e2d\u7684\u65b0\u529f\u80fd\u662f\u5f00\u5173\u8868\u8fbe\u5f0f\uff0c\u5141\u8bb8\u5728\u7b80\u6d01\u8bed\u53e5\u4e2d\u8d4b\u503c\u53d8\u91cf\u3002\u8bf7\u8003\u8651\u6b64\u65b9\u6cd5\u7684 C# 7 \u7248\u672c\uff0c\u8be5\u65b9\u6cd5\u91c7\u7528\u989c\u8272\u5e76\u8fd4\u56de\u989c\u8272\u540d\u79f0\u7684\u5341\u516d\u8fdb\u5236\u503c\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\"> \nstatic string FromRainbowClassic(string colorBand)\n{\n    switch (colorBand)\n    {\n        case &quot;Red&quot;:\n            return &quot;#FF0000&quot;;\n        case &quot;Orange&quot;:\n            return &quot;#FF7F00&quot;;\n        case &quot;Yellow&quot;:\n            return &quot;#FFFF00&quot;;\n        case &quot;Green&quot;:\n            return &quot;#00FF00&quot;;\n        case &quot;Blue&quot;:\n            return &quot;#0000FF&quot;;\n        case &quot;Indigo&quot;:\n            return &quot;#4B0082&quot;;\n        case &quot;Violet&quot;:\n            return &quot;#9400D3&quot;;\n        default:\n            return &quot;#FFFFFF&quot;;\n    };\n}\n<\/pre>\n<\/p>\n<p>With the new switch expressions in C# 8, the previous method can be written as follows, which is much more concise:<br \/>\n\u4f7f\u7528 C# 8 \u4e2d\u7684\u65b0\u5f00\u5173\u8868\u8fbe\u5f0f\uff0c\u53ef\u4ee5\u6309\u5982\u4e0b\u65b9\u5f0f\u7f16\u5199\u524d\u9762\u7684\u65b9\u6cd5\uff0c\u8fd9\u8981\u7b80\u6d01\u5f97\u591a\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nstatic string FromRainbow(string colorBand)\n{\n    return colorBand switch\n    {\n        &quot;Red&quot; =&gt; &quot;#FF0000&quot;,\n        &quot;Orange&quot; =&gt; &quot;#FF7F00&quot;,\n        &quot;Yellow&quot; =&gt; &quot;#FFFF00&quot;,\n        &quot;Green&quot; =&gt; &quot;#00FF00&quot;,\n        &quot;Blue&quot; =&gt; &quot;#0000FF&quot;,\n        &quot;Indigo&quot; =&gt; &quot;#4B0082&quot;,\n        &quot;Violet&quot; =&gt; &quot;#9400D3&quot;,\n        _ =&gt; &quot;#FFFFFF&quot;,\n    };\n}\n<\/pre>\n<\/p>\n<p>There is a lot to unpack in that example, from the lambda (=&gt;) statements to the discard (<em>). These will all be covered in later chapters, as will this example, in further detail.<br \/>\n\u5728\u8be5\u793a\u4f8b\u4e2d\uff0c\u4ece lambda \uff08=&gt;\uff09 \u8bed\u53e5\u5230\u4e22\u5f03 \uff08<\/em>\uff09\uff0c\u6709\u5f88\u591a\u4e1c\u897f\u9700\u8981\u89e3\u538b\u7f29\u3002\u8fd9\u4e9b\u90fd\u5c06\u5728\u540e\u9762\u7684\u7ae0\u8282\u4e2d\u4ecb\u7ecd\uff0c\u8fd9\u4e2a\u4f8b\u5b50\u4e5f\u5c06\u66f4\u8be6\u7ec6\u5730\u4ecb\u7ecd\u3002<\/p>\n<p>There is one more example before finishing the topic of switch expressions, and it involved tuples.Tuples are covered in detail in Chapter 4, so for now think of a tuple as a simple construct holding more than one value and defined with parentheses, like this tuple that holds a string and an int:<br \/>\n\u5728\u5b8c\u6210\u5f00\u5173\u8868\u8fbe\u5f0f\u7684\u4e3b\u9898\u4e4b\u524d\uff0c\u8fd8\u6709\u4e00\u4e2a\u793a\u4f8b\uff0c\u5b83\u6d89\u53ca\u5143\u7ec4\u3002\u5143\u7ec4\u5728\u7b2c 4 \u7ae0\u4e2d\u6709\u8be6\u7ec6\u4ecb\u7ecd\uff0c\u6240\u4ee5\u73b0\u5728\u5c06\u5143\u7ec4\u89c6\u4e3a\u5305\u542b\u591a\u4e2a\u503c\u5e76\u7528\u62ec\u53f7\u5b9a\u4e49\u7684\u7b80\u5355\u6784\u9020\uff0c\u5c31\u50cf\u8fd9\u4e2a\u5305\u542b\u5b57\u7b26\u4e32\u548c\u6574\u6570\u7684\u5143\u7ec4\u4e00\u6837\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n(string, int)\n<\/pre>\n<\/p>\n<p>In the following example, the two values passed into the RockPaperScissors method are converted to a tuple, and then the switch expression evaluates the two values in a single expression. This pattern allows for comparing more than one value during a switch statement.<br \/>\n\u5728\u4e0b\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u4f20\u9012\u7ed9 RockPaperScissors \u65b9\u6cd5\u7684\u4e24\u4e2a\u503c\u5c06\u8f6c\u6362\u4e3a\u5143\u7ec4\uff0c\u7136\u540e switch \u8868\u8fbe\u5f0f\u5728\u5355\u4e2a\u8868\u8fbe\u5f0f\u4e2d\u8ba1\u7b97\u8fd9\u4e24\u4e2a\u503c\u3002\u6b64\u6a21\u5f0f\u5141\u8bb8\u5728 switch \u8bed\u53e5\u671f\u95f4\u6bd4\u8f83\u591a\u4e2a\u503c\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ Switch expression with Tuples\n\/\/ \u4f7f\u7528\u5143\u7ec4\u5207\u6362\u8868\u8fbe\u5f0f\nConsole.WriteLine(RockPaperScissors(&quot;paper&quot;, &quot;rock&quot;));\nConsole.WriteLine(RockPaperScissors(&quot;scissors&quot;, &quot;rock&quot;));\n\nstatic string RockPaperScissors(string first, string second)\n{\n    return (first, second) switch\n    {\n        (&quot;rock&quot;, &quot;paper&quot;) =&gt; &quot;Paper wins.&quot;,\n        (&quot;rock&quot;, &quot;scissors&quot;) =&gt; &quot;Rock wins.&quot;,\n        (&quot;paper&quot;, &quot;rock&quot;) =&gt; &quot;Paper wins.&quot;,\n        (&quot;paper&quot;, &quot;scissors&quot;) =&gt; &quot;Scissors wins.&quot;,\n        (&quot;scissors&quot;, &quot;rock&quot;) =&gt; &quot;Rock wins.&quot;,\n        (&quot;scissors&quot;, &quot;paper&quot;) =&gt; &quot;Scissors wins.&quot;,\n        (_, _) =&gt; &quot;Tie.&quot;,\n    };\n}\n<\/pre>\n<\/p>\n<p>To call this method, add the following lines of code to the top-level statements:<br \/>\n\u82e5\u8981\u8c03\u7528\u6b64\u65b9\u6cd5\uff0c\u8bf7\u5c06\u4ee5\u4e0b\u4ee3\u7801\u884c\u6dfb\u52a0\u5230\u9876\u7ea7\u8bed\u53e5\u4e2d\uff1a<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nConsole.WriteLine(RockPaperScissors(&quot;paper&quot;, &quot;rock&quot;));\nConsole.WriteLine(RockPaperScissors(&quot;scissors&quot;, &quot;rock&quot;));\n<\/pre>\n<\/p>\n<p>This example will be revisited in Chapter 4 when tuples are introduced.<br \/>\n\u5728\u7b2c 4 \u7ae0\u4ecb\u7ecd\u5143\u7ec4\u65f6\uff0c\u5c06\u91cd\u65b0\u8ba8\u8bba\u6b64\u793a\u4f8b\u3002<\/p>\n<blockquote><p>\n\u25a0 Note  property patterns were also introduced in C# 8.0 and are covered in Chapter 4.<br \/>\n\u6ce8\u610f\u5c5e\u6027\u6a21\u5f0f\u4e5f\u5728 C# 8.0 \u4e2d\u5f15\u5165\uff0c\u5e76\u5728\u7b2c 4 \u7ae0\u4e2d\u4ecb\u7ecd\u3002\n<\/p><\/blockquote>\n<h2>Summary\u603b\u7ed3<\/h2>\n<p>The goal of this chapter was to expose you to numerous core aspects of the C# programming language.You examined the commonplace constructs in any application you may be interested in building. After examining the role of an application object, you learned that every C# executable program must have a type defining a Main() method, either explicitly or through the use of top-level statements. This method serves as the program\u2019s entry point.<br \/>\n\u672c\u7ae0\u7684\u76ee\u6807\u662f\u8ba9\u60a8\u4e86\u89e3C#\u7f16\u7a0b\u8bed\u8a00\u7684\u8bb8\u591a\u6838\u5fc3\u65b9\u9762\u3002\u60a8\u7814\u7a76\u4e86\u60a8\u53ef\u80fd\u611f\u5174\u8da3\u6784\u5efa\u7684\u4efb\u4f55\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684\u5e38\u89c1\u6784\u9020\u3002\u5728\u7814\u7a76\u4e86\u5e94\u7528\u7a0b\u5e8f\u5bf9\u8c61\u7684\u89d2\u8272\u540e\uff0c\u60a8\u4e86\u89e3\u5230\u6bcf\u4e2aC#\u53ef\u6267\u884c\u7a0b\u5e8f\u90fd\u5fc5\u987b\u6709\u4e00\u4e2a\u7c7b\u578b\u6765\u5b9a\u4e49Main\uff08\uff09\u65b9\u6cd5\uff0c\u65e0\u8bba\u662f\u663e\u5f0f\u7684\u8fd8\u662f\u901a\u8fc7\u4f7f\u7528\u9876\u7ea7\u8bed\u53e5\u3002\u6b64\u65b9\u6cd5\u7528\u4f5c\u7a0b\u5e8f\u7684\u5165\u53e3\u70b9\u3002<\/p>\n<p>Next, you dove into the details of the built-in data types of C# and came to understand that each data type keyword (e.g., int) is really a shorthand notation for a full-blown type in the System namespace (System.Int32, in this case). Given this, each C# data type has a number of built-in members. Along the same vein, you also learned about the role of widening and narrowing, as well as the role of the checked andunchecked keywords.<br \/>\n\u63a5\u4e0b\u6765\uff0c\u6df1\u5165\u4e86\u89e3C#\u7684\u5185\u7f6e\u6570\u636e\u7c7b\u578b\u7684\u7ec6\u8282\uff0c\u5e76\u4e86\u89e3\u5230\u6bcf\u4e2a\u6570\u636e\u7c7b\u578b\u5173\u952e\u5b57\uff08\u4f8b\u5982\uff0cint\uff09\u5b9e\u9645\u4e0a\u90fd\u662fSystem\u547d\u540d\u7a7a\u95f4\uff08\u672c\u4f8b\u4e2d\u4e3aSystem.Int32\uff09\u4e2d\u4e00\u4e2a\u5b8c\u6574\u7c7b\u578b\u7684\u7b80\u5199\u7b26\u53f7\u3002\u9274\u4e8e\u6b64\uff0c\u6bcf\u4e2aC#\u6570\u636e\u7c7b\u578b\u90fd\u6709\u8bb8\u591a\u5185\u7f6e\u6210\u5458\u3002\u540c\u6837\uff0c\u60a8\u8fd8\u4e86\u89e3\u4e86\u52a0\u5bbd\u548c\u53d8\u7a84\u7684\u4f5c\u7528\uff0c\u4ee5\u53ca\u9009\u4e2d\u548c\u672a\u9009\u4e2d\u5173\u952e\u5b57\u7684\u4f5c\u7528\u3002<\/p>\n<p>The chapter wrapped up by covering the role of implicit typing using the var keyword. As discussed, the most useful place for implicit typing is when working with the LINQ programming model. Finally, you quickly examined the various iteration and decision constructs supported by C#.<br \/>\n\u672c\u7ae0\u6700\u540e\u4ecb\u7ecd\u4e86\u4f7f\u7528var\u5173\u952e\u5b57\u8fdb\u884c\u9690\u5f0f\u952e\u5165\u7684\u4f5c\u7528\u3002\u5982\u524d\u6240\u8ff0\uff0c\u9690\u5f0f\u7c7b\u578b\u6700\u6709\u7528\u7684\u5730\u65b9\u662f\u5728\u4f7f\u7528LINQ\u7f16\u7a0b\u6a21\u578b\u65f6\u3002\u6700\u540e\uff0c\u60a8\u5feb\u901f\u68c0\u67e5\u4e86C#\u652f\u6301\u7684\u5404\u79cd\u8fed\u4ee3\u548c\u51b3\u7b56\u7ed3\u6784\u3002<\/p>\n<p>Now that you understand some of the basic nuts and bolts, the next chapter (Chapter 4) will complete your examination of core language features. After that, you will be well prepared to examine the object- oriented features of C# beginning in Chapter 5.<br \/>\n\u73b0\u5728\u60a8\u5df2\u7ecf\u4e86\u89e3\u4e86\u4e00\u4e9b\u57fa\u672c\u7684\u7ec6\u8282\uff0c\u4e0b\u4e00\u7ae0\uff08\u7b2c4\u7ae0\uff09\u5c06\u5b8c\u6210\u5bf9\u6838\u5fc3\u8bed\u8a00\u529f\u80fd\u7684\u68c0\u67e5\u3002\u4e4b\u540e\uff0c\u60a8\u5c06\u505a\u597d\u5145\u5206\u51c6\u5907\uff0c\u4ece\u7b2c5\u7ae0\u5f00\u59cb\u7814\u7a76C#\u7684\u9762\u5411\u5bf9\u8c61\u7279\u6027\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>PART II Core C# Programming CHAPTER 3 Core C# Programming Constructs, Part 1 \u6838\u5fc3 C# \u7f16\u7a0b\u6784\u9020\uff0c\u7b2c 1 \u90e8\u5206 This chapter begins your formal investigation of the C# programming language by presenting a number of bite-sized, stand-alone topics you must be comfortable with as you explore the .NET Core Framework. The first order of business is [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[22],"class_list":["post-284","post","type-post","status-publish","format-standard","hentry","category-csharp","tag-pro-csharp10-with-net6"],"_links":{"self":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/284","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=284"}],"version-history":[{"count":0,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/284\/revisions"}],"wp:attachment":[{"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=284"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=284"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=284"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}