今天我们将继续学习 C# 这门编程语言里的一些基本概念。我们将围绕前面的程序代码为大家作介绍。
using System;
namespace Project
{
internal class Program
{
private static void Main()
{
Console.WriteLine("Hello, world!");
}
}
}
如果你是完全没有学过 C# 的话,所有的概念可能对你来说,理解上有些吃力。一方面,我推荐你先学会一些基本的 C 语言概念后,再来学习 C# 的语法;另外一方面,我也会尽量把内容讲得很清楚,避免 C 语言学习后继续学 C# 的时候发生知识点关联和衔接不上的问题。
当然,如果这么讲内容的话,可能部分读者会觉得多少有一些啰嗦。一方面,请见谅;另外一方面,很多人的编程水平是参差不齐的,有些学习得很好的朋友,对编程很熟悉;概念基本上都不用怎么学就可以写代码了;而有些朋友可能初学编程,对概念很不熟悉,所以得慢慢来。为了保证尽量多的朋友能够学会 C#,所有的内容可能会讲很细,直到绝大多数朋友都能接受,因此不要嫌啰嗦。
Part 1 关键字(Keyword)
请注意代码的第一行。using
在 C# 里是一个关键字(Keyword)。所谓的关键字,就是在说,“C# 里,我使用这个词语来表示特殊用途”。
从另外一方面来讲,这一行的内容必须写成 using ...;
的形式,其中的 using
单词不能写成 use
、used
甚至 user
。关键字是永久不变的(不论是单词本身,还是单词的变形,都是不变的),而且每一个关键字都对应了语法和语义的规则,且不会变动,因此在学习的时候,只需要掌握每一个关键字的如下两点即可:
- 这个关键字怎么写;
- 这个关键字的用法到底如何。
就可以了。以后只要看到这样的写法,你就可以立即回忆出它的用法是什么,这就是学习关键字应该有的感觉。
顺带一提,所有 C# 的关键字(这里的
using
只是其中一个关键字)都是全小写的。只有一个关键字比较特殊,它不是一个单词(写成一个下划线:_
),不过这一点我们会在后面的“弃元”文章内容里作介绍。
Part 2 引用指令(Using Directive)
下面我们来说明一下,什么是一个引用指令。以 using
起头的这个形式,我们称为引用指令。它一般都写在文件的最开头。当然,你这么写也可以:
namespace Project
{
using System;
internal class Program
{
private static void Main()
{
Console.WriteLine("Hello, world!");
}
}
}
即写在 namespace
用大括号包裹起来的里面。两种写法基本没区别,只是写在外面可能更好看一点。比如说代码里的 using System;
就称为一条引用指令。using
前面说了,它是一个关键字,而后面的 System
则不是。这个 System
称为命名空间(Namespace)。命名空间指的是一个完整的项目里,规划归纳内容或者功能究竟属于哪一个类型的一种机制。system 这个单词的意思是系统,也就是说,using System;
的意思是在说,我需要引入系统自带的东西到这个项目里来。
在代码的第 9 行,我们用到了 Console.WriteLine
,它表示“把固定内容打到屏幕上显示”的这么一个功能。计算机里把这个过程叫做输出(Output)。因为这个功能是我们上手写代码就可以用的功能,所以是系统自带的功能,因此,在使用这句话的时候,你需要在最开头写上 using System;
来保证 Console.WriteLine
是系统自带的过程。
命名空间的架构使用“名称.名称.名称”的方式来表达。你可以回忆一下在学习生物的时候,我们把动植物分成界门纲目科属种七个层级。这里的命名空间的概念和这个层级关系是类似的:System
是最开头的级别,也就是最大级别。它包含了很多详细的子类别,比如说 System.Numerics
(写 using System.Numerics;
就表示你可以使用系统自带的数据处理的功能)、System.Text
(写 System.Text;
就表示你可以使用系统自带的处理文字信息的功能)等等。
命名空间采用的是固定的大写字母开头的英文单词或词组,在系统里包含了非常多的命名空间可提供你使用。单词问题来了:既然你说单词是固定的,但是你刚才说的 Numerics 啊、Text 这些,我完全都不知道,这是从哪里看的呢?命名空间是需要你先提前记住一些的。而最需要记住的就是这里的 System
。其它的其实并不重要,而你只需要先知道 System
就行了。在以后我们讲到其它的内容的时候,我们会用到别的命名空间的时候才会继续作出说明。
总之,命名空间就是用来规划项目里所有功能用的,它用来划分区分功能。
Part 3 自定义命名空间
请注意 namespace Project
这一行文字。这一行就是在定义命名空间。我们使用大括号来区分和划分定义命名空间的范围。比如这个代码里,从第 3 行开始到第 9 行结束,都属于 Project
这个命名空间的范畴。
namespace Project
{
internal class Program
{
private static void Main()
{
Console.WriteLine("Hello, world!");
}
}
}
因为入门我们还用不上 using Project;
类似的、引用自定义命名空间的指令,因此只需要知道一点,命名空间是通过 namespace
这一行文字来规定的。是的,namespace
也是 C# 里的一个关键字。它的功能就是用来定义一个命名空间。这里你记住这么用就可以了,知道它就是一个规定命名空间的一个意思就可以了。
Part 4 主方法(Main Method)
另外一个 C# 比较重要的概念就是主方法。主方法是整个程序开始运行、跑起来的入口。换句话说,只要我们写了 private static void Main()
的话,那么就是在说明,“整个程序都从这里开始从上到下依次执行功能”。比如这个代码里:
using System;
namespace Project
{
internal class Program
{
private static void Main()
{
Console.WriteLine("Hello, world!");
}
}
}
使用了大括号来表示,主方法从第 8 行开始,到第 10 行结束,整个这一部分都属于主方法的范围。而大括号本身没有实际的执行意义,所以真正在执行功能的只有第 9 行。
主方法的头部(Signature,也叫签名)的所有可能写法可以总结成如下的内容:
主方法签名
访问修饰符? 'static' 类型 'Main' '(' 参数? ')'
访问修饰符
'public'
'private'
参数
'string[] args'
类型
'void'
'int'
这个写法你可能需要了解一下。以后我们在说明语法的格式的时候,会广泛采用这种写法。下面我们就来说明一下,这个记号的书写规则。
Part 5 语法格式的书写约定
其中,我们把我们要描述的一个语法使用中文名(或者英文单词)来表示,写在左上角;然后把它的格式,写在下面。比如主方法的语法格式就是 访问修饰符? 'static' 类型 'Main' '(' 参数? ')'
。
接着,在这个写法里用到了“访问修饰符”、“类型”、“参数”等使用中文名表达的中间元素。这些元素都可以在下面的内容里找到写法。比如说“访问修饰符”可以使用 public
或者 private
,选择其中一个写法,填入到前面主方法格式的“访问修饰符”的对应位置上。旁边带有的问号 ?
称为通配符。所有这种描述下的通配符一共有三种:
- 问号(
?
):表示前面的这个内容可以有,也可以没有。有的话,最多只能有一个; - 星号(
*
):表示前面的这个内容可以有,也可以没有,而且还不限定出现次数; - 加号(
+
):表示前面的这个内容必须有,且至少有一个; - 没有记号:必须有,且只能有一个。
举个例子。“访问修饰符?
”可以写 public
、private
、甚至不写出来,但不能写 private public
或者别的,因为这样的话,算作出现两次访问修饰符了。
然后是单引号的内容。单引号里的内容是固定不变的内容。换句话说,这个语法格式下,这里就必须写成这个单词或者词组,且不能修改大小写。
那么,主方法的这么长的语法格式就可以被理解成:先写一个访问修饰符(private
或 public
,也可以不写),然后是 static
单词,然后是类型(void
或 int
里选择一个),然后是 Main
单词,然后是开小括号,然后是参数(可以写,写的话必须写成 string[] args
,也可以不写),然后是闭小括号。
我们可以利用这个格式,来表述引用指令的语法格式:
引用指令
'using' 名称 ';'
其中,“名称”是随意的英文单词,所以没有固定的书写格式,因此这里就省略“名称”的具体书写格式了。而命名空间定义的格式如下:
命名空间定义
'namespace' 命名空间名称 '{' 所有可以属于该命名空间的内容 '}'
其中 '{' 所有可以属于该命名空间的内容 '}'
就对应了代码的这一段:
{
internal class Program
{
private static void Main()
{
Console.WriteLine("Hello, world!");
}
}
}
所以,这个格式,你看明白了吗?那么,语法格式的约定我们就说到这里。
我其实并不是很像让大家学习这个东西。初学来说,学习这个东西有些麻烦了。但是因为先掌握这个,以后描述很多东西都会很轻松,所以这一点先介绍也不是坏事。
Part 6 标识符(Identifier)
标识符是一个我们可以直接写到代码里,且是我们自定义的词语、编译器也不管你的符号。在上一节的代码里,System
、Program
、Main
均属于标识符。
可能你会问我,System
、Main
这些单词不是固定的吗?是的,但你改成别的东西之后,编译器并不会认为有问题;相反,其它依赖于这些符号的地方才会产生错误信息,但本身 System
和 Main
这些符号并不会影响什么。这些我们称为标识符。标识的识读作 zhì,即和“标志”读音一致。
1-1 标识符命名规则
为了编译器可以识别和认定一个自定义的词语是一个标识符,我们有如下的约定:
- 由数字、字母、下划线、@ 符号、中文字符、日语、韩语等常见语言字符构成。
- 第一个字符不能是数字,但可以是字母和下划线,且还可以是原义符号
@
; - 当你想使用关键字的写法作为标识符的时候,需要在单词前面追加原义符号
@
,其它的情况,原义符号则可有可无。原义符号只能有一个,且只能放在最开始。 - 大小写敏感。
这个规定我不知道你能否理解。比如说,Program
就是一个正确的标识符、Main
也是、System
也是。另外,在 C# 里,namespace
是一个关键字,但你又确实想把 namespace
作为标识符来使用的话,需要追加原义符号,即改写成 @namespace
,编译器就知道这个是一个叫 namespace 的标识符了。
写成语法格式就是:
标识符格式
'@'? 开头字符 普通字符*
开头字符
字母
下划线
普通字符
数字
字母
下划线
标识符可以用在自定义的命名空间上、方法名上、类名上,等等其它的地方。你现在学到的程序,由于没有数据类型,因此无法详细介绍。下一节我们就会进入数据类型这一节内容;那么那个时候,你就可以使用自定义的标识符作为变量来使用了。
1-2 标识符命名规范
前面说到了命名规则,它们是强制性的规定,必须要满足的。下面我们来说一下软性规定。这种规定不需要你一定满足,但希望你满足。
标识符有四种基本的命名规则:
- 驼峰命名法(camelCase)
- 帕斯卡命名法(PascalCase)
- 匈牙利命名法(typeCase)
- 蛇命名法(snake_case)
其中匈牙利命名法需要配合类型作为介绍,因此我们这里就不作说明了。
驼峰命名法是说,如果一个标识符需要多个有意义的单词构成的话,第一个单词的首字母使用小写,而其它单词全部首字母大写,剩下的字符均使用小写的一种写法,比如说 checkWhetherThatGirlIsBeautiful
。第一个单词 check
的首字母是小写的,而后续的单词,首字母全部是大写的。
帕斯卡命名法和驼峰命名法只差一点:第一个单词的首字母也得大写。所以帕斯卡命名法的话,前面这个标识符就得写成 CheckWhetherThatGirlIsBeautiful
。
最后,蛇命名法需要把所有单词全部小写,然后单词之间用下划线分隔,那么就得是 check_whether_that_girl_is_beautiful
这样的。
在 C# 里,我们一般对命名空间、方法名使用帕斯卡命名法。也就是说,我们一般是见不到小写开头的命名空间名称,也一般见不到小写开头的方法名。前面的 Main
方法(我们叫主方法)的 M 也是大写的。学习过 C 语言的朋友应当知道,C 语言里的 main 函数(主函数)是小写起头的。C# 是大写起头,因此需要注意。
标识符在 C# 里起着重要的意义。标识符是大小写敏感(Case Sensitive)的,因而 main 和 Main 是两个不同的标识符。
Part 7 缩进(Indenting)
缩进并非是 C# 首创。C 语言里,缩进就已经存在了。缩进指的是代码里没有执行意义的那些空格。举个例子:
using System;
namespace Project
{
internal class Program
{
private static void Main()
{
Console.WriteLine("Hello, world!");
}
}
}
在这段代码里,第 5 行(internal class Program
)前面有 4 个空格。为了保证代码层级关系很清晰,我们写代码需要添加这样的空白来保证代码更好看。比如上面这样写代码,我们就可以清晰地知道,namespace Project
包含了 Program
以及里面的这些东西;而 internal class Program
则又包含了 Main
以及里面的东西;Main
方法则又包含了里面的执行逻辑(输出一行文字到屏幕上)。
缩进在划分层级关系的时候相当有用。空白字符是不起到执行意义的,但对我们理解代码来说,非常有意义。
一般来说,缩进分空格(Space)和制表符(Tab)两种,比如例子里,缩进就采用了空格作为缩进字符。你也可以用制表符,不过并不建议你混用两种字符类型,因为空格和制表符都是“看不见”的,混用可能会导致代码出现隐藏的问题。
制表符就是你键盘上左起第一列里写了“Tab”字样的按键。按下这个按键,就会自动插入一个制表符。一个制表符的长度相当于 8 个空格;但在代码里,一般相当于 4 个空格的长度。所以如果插入空格的话,需要按 4 下空格按键,这样就可以插入 4 个空格,和一个制表符长度相同。
Part 8 注释(Comment)
可以从英文名里面看出,注释用的是一个叫做 comment 的单词。comment 原本的意思是评论(当然,现如今很多日本朋友也会把 comment 理解成弹幕的意思,虽然日语的 danmaku 也是弹幕)。这里我们使用“评论”这层释义。
我们可以对代码里的任何地方插入注释。注释里可以写上任何我们想写的话,来作为这行代码(或这段代码)的解释说明或者是评论。举个例子:
using System; // The 'using' statement.
/*
The namespace statement. In addition, this statement is unncessary.
In other words, you don't need to write this.
*/
namespace Project
{
/*
The class declaration, which is too complex to introduce.
Therefore, I won't introduce about this now.
*/
/**
* <summary>
* Provides main method of this program.
* </summary>
*/
internal class Program
{
/// <summary>
/// The main entry point of this program.
/// </summary>
private static void Main()
{
// Output a line of text onto the screen.
Console.WriteLine("Hello, world!");
}
}
}
其中,所有以 //
和 ///
开头的部分,全部称为注释。C# 的注释一共有四种:
- 单行注释(
//
开头); - 多行注释(以
/*
开头,以*/
结尾,这两个东西可以不在同一行。这两个东西包裹起来的所有部分都是注释); - 经典文档注释(
/**
开头,以*/
结尾,和多行注释用法完全一样,只是把开头的/*
改成/**
而已); - C# 专用文档注释(
///
开头的单行注释文字)。
单行注释以 //
起头,只要写了这个起头的标记,后面的所有东西都会被认为是注释文字。可以从示例里看出,注释文字是随便写的,不需要遵循任何 C# 代码的语法规则,它完全可以是一句英语,甚至写中文也是可以的。这就是注释的一大特殊用途:注释文字是随便写什么都可以的,因为编译器知道是注释,因而它们并不参与编译和程序的运行。
而多行注释和单行注释用法完全一样,也是起到补充说明代码的具体逻辑用的。只是用到了 /*
和 */
作为定界符,因此从这一点来说,它和单行注释不一样。
一般来说,我们都不怎么用多行注释;相反,单行注释用得很多。即使是占据多行文字,我们也会每一行都加上 //
来写单行注释,这样整体看起来就是一个多行注释了:
// The namespace statement.
// In addition, this statement is unncessary;
// in other words, you don't need to write this.
namespace Project
{
}
比如这样。
文档注释我们会在“类”的内容里讲到,这里就不说明了(对于我们现在的内容来说,也没有什么特殊的意义),因为这里的
summary
这些单词是固定的,但它们都有特殊意义,因此在这里说明会显得很臃肿。
Part 10 总结
本文我们初步了解了 C# 代码的基本构造,只有 internal class Program
我们在前面没有讲了。这个叫做类(Class),因为内容很繁琐,所以你当成固定的文本记住就行。到时候我们讲到类的时候,会对这个写法作出详细说明。
我们了解到,整个程序的大体构造是“引用指令”、“命名空间声明”、“类”、“主方法”以及执行逻辑,是按照顺序写的,这就是我们本节需要让大家掌握的内容。下一节我们会继续对 Console
等概念作出补充说明。
我们把基本的 C# 概念全部给大家介绍了一通。我不知道你能接受多少,但它们在后续的内容里我们还会提到。如果不怎么记得的话,还可以回来看,所以不必担心今天的内容的难度多大。
实际上,今天就作为理论学习一下就可以,因此不必带有负担。