C# 词法结构
最后修改于 2025 年 5 月 16 日
与人类语言一样,计算机语言也具有明确定义的词法结构。 C# 程序的源代码由标记(tokens)组成,这些标记是代码中最小的含义元素。 标记包括标识符(例如变量和方法名称)、关键字(保留字,如 if、class、public)、字面量(固定值,如数字和字符串)、运算符(如 +、-、=)、分隔符(如括号、大括号、逗号和分号)、注释和空白。 C# 编译器读取源代码并将其分解为这些标记,以正确理解和处理程序。
C# 程序使用 Unicode 字符集中的字符编写,该字符集允许使用来自世界各地多种语言的各种符号和脚本。 这意味着 C# 源代码不仅可以包含标准的拉丁字母和数字,还可以包含来自其他字母表、数学符号,甚至是表情符号的字符。 Unicode 支持使开发人员能够使用他们的母语编写标识符和字符串字面量,使 C# 成为一种全球可访问的编程语言。
C# 注释
注释供人类用于阐明源代码。 C# 中有三种类型的注释。 单行注释、多行注释和 XML 注释。 XML 注释可以提取到 HTML 文件。
多行注释用 /* */ 字符括起来。 单行注释以两个正斜杠开头。
/*
This is Program.cs
Author: Jan Bodnar
ZetCode 2022
*/
// A C# statement
Console.WriteLine("This is Comments program");
C# 编译器会忽略注释。
/* This is Program.cs /* Author: Jan Bodnar */ ZetCode 2022 */
注释不能嵌套; 上面的代码无法编译。
C# 空白
C# 中的空白指的是源代码中使用的空格、制表符和换行符。 它有两个主要目的:分隔编译器的标记和提高开发人员的代码可读性。
空白的作用
在某些地方需要空白来区分关键字、标识符和符号。 它还可以提高代码的清晰度,使其更易于阅读和维护。 虽然在某些情况下是必需的,但过多的空白不会影响编译。
int i = 0; string message = "Hello, World!";
在此示例中,空白将 int 关键字与变量名 i 分隔开,确保编译器正确解释每个标记。
C# 中的空白规则
空白必须放置在类型声明及其标识符之间,例如 int value。 但是,它不能在关键字或变量名中使用——int my Variable 是无效的。 编译器会忽略标记之间的额外空格。 适当的格式可以提高可读性,而不一致的间距会使代码难以阅读。
int a=1; // No space around '=' (valid but less readable) int b = 2; // Proper spacing improves clarity int c = 3; // Extra spaces do not affect compilation
空白的最佳实践
使用一致的缩进和间距可以提高可读性。 遵循标准的 C# 编码约定(例如在运算符周围放置空格)可以增强清晰度。 避免不必要的空白,因为它不会有助于更好的结构。
// Poorly formatted code:
if(x==10){Console.WriteLine("Hello");}
// Well-formatted code:
if (x == 10)
{
Console.WriteLine("Hello");
}
尽管编译器会忽略多余的空白,但结构良好的代码可以提高可维护性和可读性,确保以更专业和更有组织的方式进行 C# 开发。
C# 变量
变量是一个标识符,它引用保存值的内存位置。 变量在程序执行期间被赋值。 标识符可以包含字母、数字和下划线,但必须以字母或下划线开头,不能以数字开头。
C# 区分大小写,因此 Name、name 和 NAME 是不同的变量。 关键字不能用作标识符,除非以 @ 为前缀(例如,@int),但不建议这样做。
string userName; int _count; DateTime birthDate;
这些是有效的标识符。
string 123name; // Starts with a digit int %count; // Contains invalid character DateTime birth date; // Contains space
这些是无效的标识符。
public class VariablesExample
{
public static void Main(string[] args)
{
string name = "Robert";
string Name = "Julia";
Console.WriteLine(name); // Outputs: Robert
Console.WriteLine(Name); // Outputs: Julia
}
}
该程序演示了区分大小写,因为 name 和 Name 被视为单独的变量。
C# 字面量
字面量是给定类型中特定值的直接表示。 C# 支持各种字面量类型,包括布尔值、整数、浮点数、字符串、字符和日期。 与在运行时接收其值的变量不同,字面量在编译时被赋值。
int age = 29; string nationality = "Hungarian";
在上面的示例中,29 是一个整数文字,而 "Hungarian" 是一个字符串文字。
bool isSingle = true;
string name = "James";
string job = null;
double weight = 68.5;
DateTime birthDate = DateTime.Parse("November 12, 1987");
Console.WriteLine($"His name is {name}");
if (isSingle)
{
Console.WriteLine("He is single");
}
else
{
Console.WriteLine("He is in a relationship");
}
Console.WriteLine($"His job is {job}");
Console.WriteLine($"He weighs {weight} kilograms");
Console.WriteLine($"He was born in {birthDate:yyyy}");
上面的示例演示了不同的字面量类型
bool字面量可以保存true或false。- 值
"James"是一个字符串字面量。 - 关键字
null表示未分配的值。 68.5是一个浮点字面量。- 日期
November 12, 1987是一个日期字面量。
$ dotnet run His name is James He is single His job is He weighs 68.5 kilograms He was born in 1987
C# 运算符
运算符是一个符号,用于对某个值执行操作。 运算符用于表达式中,以描述涉及一个或多个操作数的操作。
+ - * / % ^ & | ! ~ = += -= *= /= %= ^= ++ -- == != < > &= >>= <<= >= <= || && >> << ?:
这是 C# 运算符的部分列表。 我们将在本教程的后面部分讨论运算符。
C# 分隔符
分隔符是一个或多个字符的序列,用于指定纯文本或其他数据流中各个独立区域之间的边界。
[ ] ( ) { } , : ;
string language = "C#";
双引号字符用于标记字符串的开头和结尾。 分号 (;) 字符用于结束每个 C# 语句。
Console.WriteLine("Today is {0}", DateTime.Today.ToString("M/d"));
括号(圆括号)用于标记方法签名。 签名由方法参数组成。 大括号用于表示计算后的值。
int[] array = new int[5] {1, 2, 3, 4, 5};
方括号 [] 用于表示数组类型。 它们也用于访问或修改数组元素。 大括号 {} 也用于初始化数组。 大括号也用于变量内插或括住方法或类的主体。
int a, b, c;
逗号字符可用于在同一行代码上使用多个声明。
C# 关键字
C# 中的关键字是保留字,在语言中具有特殊含义。 它们用于定义变量、控制程序流程和执行逻辑运算,从而确保结构化和功能性的代码库。
C# 包括广泛的关键字,例如 if、else、for、while、base、false、float、catch 和 this。 这些关键字在编程的各个方面发挥着至关重要的作用,并在整个教程中逐步介绍。
for (int i = 0; i <= 5; i++)
{
Console.WriteLine(i);
}
在上面的示例中,int 关键字定义了一个变量类型,而 for 关键字启动了一个循环,演示了 C# 中的基本控制流和数据处理。
C# Unicode 支持
C# 使用 Unicode 字符集,允许标识符、字面量和注释包含来自各种语言的字符,例如西里尔语、中文或阿拉伯语。 这使得 C# 适用于国际化。
public class UnicodeExample
{
public static void Main(string[] args)
{
string имя = "Анна"; // Russian identifier and string
Console.WriteLine($"Имя: {имя}");
string 名前 = "太郎"; // Japanese identifier and string
Console.WriteLine($"名前: {名前}");
}
}
此示例在俄语和日语中使用 Unicode 标识符和字面量,演示了 C# 对全局字符集的支持。
C# 预处理器指令
预处理器指令是在编译之前处理的特殊指令。 它们允许条件编译、符号定义和其他编译时行为。 所有预处理器指令都以 # 开头。
这些指令不生成可执行代码,但会影响编译器处理源代码的方式。 常见的预处理器指令包括 #define、#if、#else、#elif、#endif、#region 和 #pragma。
#define DEBUG
public class PreprocessorExample
{
public static void Main(string[] args)
{
#if DEBUG
Console.WriteLine("Debug mode is active");
#else
Console.WriteLine("Debug mode is inactive");
#endif
}
}
在上面的例子中
#define DEBUG声明一个预处理器符号。#if DEBUG检查是否定义了符号DEBUG。#else指定如果未定义符号的替代代码路径。#endif标记条件指令的结束。
预处理器指令对于管理调试和发布配置、组织代码块以及增强编译器行为而无需更改运行时执行非常有用。
C# 行终止符
行终止符标记源代码中一行的结束。 在 C# 中,有效的行终止符包括回车符 (\r)、换行符 (\n) 或组合 (\r\n)。 它们会影响编译器解析标记的方式。
与某些语言不同,C# 不需要用分号终止每一行,但语句必须用分号分隔。 行终止符有助于编译器识别标记边界。
public class LineTerminatorExample
{
public static void Main(string[] args)
{
Console.WriteLine("Line 1");
Console.WriteLine("Line 2");
}
}
每个语句都以分号结尾,并用行终止符分隔,确保编译器正确解析。
C# 约定
约定是编写一致且可读的 C# 代码的推荐做法。 虽然编译器不强制执行这些约定,但它们可以提高代码的可维护性和协作性。 以下是 C# 的主要约定
- PascalCase 用于标识符:类、方法和属性以大写字母开头(例如,
MyClass、GetName)。 - 接口名称:以
I开头(例如,IEnumerable)。 - 注释:放在单独的行上,而不是代码行的末尾,以保证清晰。
- 每行一个语句:避免在单行上放置多个语句。
- 有意义的名称:使用描述性标识符,例如
customerName,而不是cn。 - 常量:使用带有下划线的大写字母(例如,
MAX_COUNT)。 - 大括号:将左大括号放在代码块的新行上。
- Main 方法参数:将字符串数组参数命名为
args。 - 关键字顺序:在声明中将
public放在static之前。 - 缩进:对嵌套代码使用一致的 4 个空格缩进。
- 文件命名:将文件名与主类名称匹配(例如,
Program.cs对应于Program类)。
本文探讨了 C# 的词法结构,包括注释、变量、字面量、运算符、分隔符和关键字等标记。 还涵盖了 Unicode 支持、预处理器指令和行终止符等其他主题,以提供全面的理解。 遵守 C# 约定可确保高质量、可维护的代码。
来源
作者
列出所有 C# 教程。