首页 > Python基础教程 >
-
C# 语法基础
第一次见到 C# 程序可能会有一些奇怪,程序中有一些 {
、}
、[]
这样的符号。然而在逐渐深入了解 C# 语言的过程中,对这些符号和 C# 语言特有的其他符号会越来越熟悉,甚至会喜欢上它们。
本篇,我们继续从演示一个简单的程序示例开始,解释该程序的功能和它的各组成部分。同时,介绍一些 C# 语言的基本语法。
简单的 C# 程序示例
using System; /* 告诉编译器这个程序使用 System 命名空间中的类型 */
namespace ConsoleApp /* 声明一个新命名空间,名称为 ConsoleApp */
{
class Program /* 声明一个新的类类型,名称为 Program */
{
/// <summary>
/// Main 是一个特殊方法,编译器用它作为程序的起始点
/// </summary>
static void Main()
{
int number; /* 声明一个名为 number 的变量 */
// 为 number 赋值
number = 1;
// 输出一行文字
Console.WriteLine("C# 语法基础");
// 还是输出一行文字
Console.WriteLine($"变量 number 的值是:{number}");
}
}
}
输出
C# 语法基础
变量 number 的值是:1
上面程序中每一行代码的作用:
第 1 行
: 告诉编译器这个程序使用 System
命名空间中的类型
第 3 行
: 声明一个新命名空间,名称为 ConsoleApp
- 新命名空间从第 4 行的左大括号(`{`)开始一直延伸到第 24 行与之对应的右大括号(`}`)结束
- 在这部分里声明的任何类型都是该命名空间的成员
第 5 行
: 声明一个新的类类型,名称为 Program
- 任何在第 6 行和第 23 行的两个大括号中间声明的成员都是组成这个类的成员
第 10 行
: 声明一个名称为 Main
的方法
- `Main` 是一个特殊方法,编译器用它作为程序的起始点
第 12 行
: 声明一个名为 number
的变量
第 15 行
: 为 number
赋值
第 18 行和第 21 行
: 输出一行文字
关于 C# 的语法,要介绍的内容有很多,我们从简单的开始。
关键字
为了使编译器能够解释代码,C# 中的某些单词具有特殊地位和含义,它们称为关键字。关键字是预定义的保留标识符,对编译器有特殊意义。在上面的代码中,class
,static
和 void
均是关键字。
编译器根据关键字识别代码的结构与组织方式。由于编译器对这些单词有着严格的解释,所以必须将关键字放在特定位置。如违反规则,编译器会报错。
C# 关键字列表
abstract | as | base | bool |
break | byte | case | catch |
char | checked | class | const |
continue | decimal | default | delegate |
do | double | else | enum |
event | explicit | extern | false |
finally | fixed | float | for |
foreach | goto | if | implicit |
in | int | interface | internal |
is | lock | long | namespace |
new | null | object | operator |
out | override | params | private |
protected | public | readonly | ref |
return | sbyte | sealed | short |
sizeof | stackalloc | static | string |
struct | switch | this | throw |
true | try | typeof | uint |
ulong | unchecked | unsafe | ushort |
using | using static | virtual | void |
volatile | while |
C# 上下文关键字列表
上下文关键字用于在代码中提供特定含义,但它不是 C# 中的保留字。 一些上下文关键字(如 partial
和 where
)在两个或多个上下文中有特殊含义。
add | alias | ascending |
async | await | by |
descending | dynamic | equals |
from | get | global |
group | into | join |
let | nameof | on |
orderby | partial(类型) | partial(方法) |
remove | select | set |
unmanaged(泛型类型约束) | value | var |
when(筛选条件) | where(泛型类型约束) | where(查询子句) |
yield |
标识符
标识符是一种字符串,开发者用来命名如变量、方法、参数和许多后面将要阐述的其他程序结构。有效标识符必须遵循以下规则:
- 不得将关键字用作标识符。
-
标识符必须以字母
a-z A-Z
或下划线_
符号开头。 -
标识符可以包含字母
a-z A-Z
,数字0-9
和下划线_
符号。 -
标识符不得包含任何特殊字符(例如
!@ $ *.’[]
等),除了下划线_
。 -
关键字附加“
@
”前缀可作为标识符使用,例如:可命名局部变量@return
类似地,可命名方法@throw()
。
选择简洁而有意义的名称,这使代码更容易理解和重用。要选择清晰(甚至是详细)的名称,尤其是在团队中工作,或者开发要由别人使用的库的时候。
标识符区分大小写。例如,变量名 myVar
和 MyVar
是不同的标识符。举个例子,在下面的代码片段中,变量的声明都是有效的,并声明了不同的整型变量。但使用如此相似的名称会使代码更易出错并更难调试,后续需要调试代码的人会很不爽。
// 语法上有效,但非常混乱
int totalCycleCount;
int TotalCycleCount;
int TotalcycleCount;
标识符的大小写规则
标识符有两种基本的大小写风格:
- PascalCasing
- camelCasing
PascalCasing 约定用于除参数名称之外的所有标识符,将每个单词的第一个字符大写(包括超过两个字母的首字母缩写),如以下示例所示:
PropertyDescriptor
HtmlTag
(在 HtmlTag
中, 由于首字母缩写词 HTML
的长度超过两个字母,所以仅首字母大写。)
这里有一种特殊情况,即遇到两个字母的首字母缩略词时,两个字母都要大写,如下面的标识符所示:
IOStream
camelCasing 约定仅用于参数名称,将除第一个单词之外的每个单词的第一个字符大写,如以下示例所示。 该示例还显示,以 camelCasing 标识符开始的双字母缩写词都是小写的。
propertyDescriptor
ioStream
htmlTag
标识符命名规范
- 要更注重标识符的清晰而不是简短。
- 不要在标识符名称中使用单词缩写。
- 不要使用不被广泛接受的首字母缩写词,即使被广泛接受,非必要也不要用。
- 不要使用下划线来区分单词,也不要在标识符中的任何位置使用下划线。
参考微软官方“框架设计准则”,链接地址:https://docs.microsoft.com/zh-cn/dotnet/standard/design-guidelines/
类型定义
C# 所有代码都出现在一个类型定义的内部,最常见的类型定义以关键字 class
开头。
类型名称(本例是 Program
)可以随便取,但根据约定,它应当使用 PascalCase 风格。就本例来说,可选择的名称包括 Greetings
,HelloInigoMontoya
,Hello
或者简单地称为 Program
。
class Program
{
// ...
}
Main
方法
Main
方法是 C# 应用程序的入口点。 (库和服务不要求使用 Main
方法作为入口点)。Main
方法是应用程序启动后调用的第一个方法。
static void Main()
{
// ...
}
C# 要求 Main
方法返回 void
或 int
, 而且要么无参,要么接收一个字符串数组。
static int Main(string[] args)
{
// ...
return 0;
}
args
参数是用于接收命令行参数的字符串数组,用 System.Environment.CommandLine
获取执行程序所用的完整命令。
Main
返回的 int
是状态码,标识程序执行是否成功。返回非零值通常意味着错误。
虽然 Main
方法声明可进行某种程度的变化,但关键字 static
和方法名 Main
是始终都是需要的。以下是有效 Main
示例:
static void Main() { }
static int Main() { }
static void Main(string[] args) { }
static int Main(string[] args) { }
static async Task Main() { }
static async Task<int> Main() { }
static async Task Main(string[] args) { }
static async Task<int> Main(string[] args) { }
花括号、方法体和代码块
{
...
}
一般来说,所有的 C# 方法都使用花括号标记方法体的开始和结束。这是规定,不能省略。只有花括号({}
)能起这种作用,圆括号(()
)和方括号([]
)都不行。
花括号还可用于把方法中的多条语句合并为一个单元或块。
语句和语句分隔符
语句是描述一个类型或告诉程序去执行某个动作的一条源代码指令,C# 通常用分号标识语句结束。每条语句都由代码要执行的一个或多个行动构成。声明变量、控制程序流程或调用方法,所有这些都是语句的例子。
例如,下面的代码是一个由两条简单语句组成的序列。第一条语句定义了一个名称为 var1
的整型变量,并初始化它的值为 5
。第二条语句将变量 var1
的值打印到屏幕窗口。
int var1 = 5;
System.Console.WriteLine("The value of var1 is {0}", var1);
语句可以是以分号结尾的单行代码,也可以是语句块中的一系列单行语句。 语句块括在括号 {}
中,并且可以包含嵌套块。 以下代码演示了两个单行语句示例和一个多行语句块:
namespace ConsoleApp
{
class Program
{
static void Main()
{
// Declaration statement.
int counter;
// Assignment statement.
counter = 1;
// Error! This is an expression, not an expression statement.
// counter + 1;
// Declaration statements with initializers are functionally
// equivalent to declaration statement followed by assignment statement:
int[] radii = { 15, 32, 108, 74, 9 }; // Declare and initialize an array.
const double pi = 3.14159; // Declare and initialize constant.
// foreach statement block that contains multiple statements.
foreach (int radius in radii)
{
// Declaration statement with initializer.
double circumference = pi * (2 * radius);
// Expression statement (method invocation). A single-line
// statement can span multiple text lines because line breaks
// are treated as white space, which is ignored by the compiler.
System.Console.WriteLine("Radius of circle #{0} is {1}. Circumference = {2:N2}",
counter, radius, circumference);
// Expression statement (postfix increment).
counter++;
} // End of foreach statement block
} // End of Main method body.
} // End of SimpleStatements class.
}
由于换行与否不影响语句的分隔,所以可将多条语句放到同一行,C# 编译器认为这一行包含多条指令。例如,下面的代码在同一行包含了两条语句。
int var1 = 5;System.Console.WriteLine("The value of var1 is {0}", var1);
C# 还允许一条语句跨越多行。同样地,C# 编译器根据分号判断语句结束位置。
System
.Console.
WriteLine
("The value of var1 is {0}",
var1);
空白
程序中的空白指的是没有可视化输出的字符,程序员在源代码中使用的空白将被编译器忽略。但使代码更清晰易读。空白字符包括:空格(Space)、制表符(Tab)、换行符、回车符。
例如,下面的代码段会被编译器完全相同地对待而不管它们表面上的区别。
// 推荐的格式
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
}
}
// 连在一起(不推荐的格式)
class Program {static void Main(string[] args){Console.WriteLine("Hello World!");}}
为了增强可读性,用空白对代码进行缩进很有必要。写代码时要遵循制订好的编码标准和约定,以增强代码的可读性。
注释
注释,是代码中的一些“说明性文字”。注释本身不会参与程序的编译和运行,仅仅供程序员阅读。
注释分为:单行注释、多行注释、文档注释。
单行注释的符号是 2 条斜线(请注意斜线的方向),2 条斜线右侧的内容就是注释,左侧的代码不会受影响。
多行注释以“/*”开始,以“*/”结束,之间的内容就是注释,可以包含多行。
文档注释写在类、方法或属性,它的符号是 3 条斜线“///”。
/// <summary>
/// XML(文档)注释
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
// 单行注释
var item = (Name: "eggplant", Price: 1.99m, perPackage: 3);
/* 多行注释(可以写一行,也可以写多行) */
var date = DateTime.Now;
/*
多行注释
注释注释
注释
*/
Console.WriteLine($"On {date}, the price of {item.Name} was {item.Price:C2} per {item.perPackage} items.");
/*
* 这样比较好看
* 嗯呢,好看
* 漂亮
*/
Console.WriteLine();
Console./*这是有多闲才这么写啊*/WriteLine();
}
编译器会忽略所有的注释,所以生成的程序集中看不到源代码中的任何注释。
总结
一门语言的语法是一套规则,用于管理语言中各有效语句组合在一起的方式。
原文链接:https://www.vinanysoft.com/c-sharp-basics/introducing/c-sharp-syntax-fundamentals/