撰写了文章 更新于 2019-12-31 11:09:39
从C#开始的编程入门——数据的名字
数据的名字——变量
”你的名字是?“
我的名字是李华。

如果今天刚开学有一千个同学都要问你的名字,每次都现写这也太累了。
你找了张纸,写下了你的名字。

再有人问你名字,你就直接给他看了。

我们通过变量(variable),来访问数据。脱离计算机、抽象地来说,你可以认为我们把数据放在了一个变量里,这个变量就代表着这个数据,我们通过这个变量就可以拿到我们保存的数据。(但严格来说,这并不正确。被我们取名字的并不是数据本身,容纳数据的也不是变量。)
上面的两行代码代表我们取了一个新名字,name。等号右边是它的值,它的左边代表它的类型。C#是静态语言,我们需要在(大部分时候)声明(declare)在日语中,这里的declare被翻译为“宣言”变量时明确告诉编译器这个变量的类型。就像这样把类型名称放在变量名前,以空格隔开。一旦变量被声明,我们就可以在其他地方使用它,并且不需要加上它的类型名称。(不是所有可以标注类型的语言都把类型放在变量名前面,比如Swift就不是,但是这是一个设计方面的问题)这句话我们可以读作:“声明一个叫name的string类型的变量,并把“Li Hua”赋值(assign)给它”。注意,这个等号,确实是等号,但是它的含义不是“等于”,而是“令它为”的意思。(如果看到“令”字你想到了let,我可以多说一句,JavaScript和Swift还真用let来声明一个名称)
取名字的基本法
名字很重要,不能乱取。一般来说我们使用英文字母作为变量名。变量名可以包含字母、数字、下划线。但是必须以下划线、字母开头。

现在很多编程语言都支持Unicode字符作为变量名和其他自定义名称,但是我觉得主要还是不太搭,而且切换输入法麻烦,所以一般还是只使用英文字母。上面这样是合法的,但是并不好玩,想象一下每次你需要输入一个变量名的时候你还得切换输入法。。。
年龄和姓名——数据类型
通常来说,我们的年龄都是一个数字,并且是非负的(我确实是想不到怎么活出负数的年龄)。而我们的名字是由各种语言文字书写的文字。(如何用同样的编码方案保存世界所有的语言符号是一个问题,Unicode的出现解决了很多难题。)数字、文字,我们称之为不同的数据类型。
比如刚才的名字变量name,它的类型是string,即字符串。
那么现在我们声明一个变量表示我们的年龄。

表示数字的类型
很显然,哪怕读者您还在读小学,您也知道数字不一定是整数,还有小数。C#中的数值类型也不仅仅只有整数。下面是C#中内置的所有表示数字的类型。
| C#类型 | 范围 | 描述 |
|---|---|---|
| sbyte | -128 - 127 | 有符号8位整型 |
| byte | 0 - 255 | 无符号8位整型 |
| short | -32678 - 32767 | 有符号16位整型 |
| ushort | 0 - 65535 | 无符号16位整型 |
| int | -2147483648-2147483647 | 有符号32位整型 |
| uint | 0 - 4294967295 | 无符号32位整型 |
| long | -9223372036854775808 - 9223372036854775807 | 有符号64位整型 |
| ulong | 0 - 18446744073709551615 | 无符号64位整型 |
| float | ±1.5 x 10−45 - ±3.4 x 1038 | 精度为6-9位,大小为4字节 |
| double | ±5.0 × 10−324 - ±1.7 × 10308 | 精度为15到17位,大小为8字节 |
| decimal | ±1.0 x 10-28 - ±7.9228 x 1028 | 精度28到29位,大小为16字节 |
u代表unsigned。(C/C++程序员注意,C#里面并没有unsigned关键字)short在中文里通常称作短整型,long则是长整型。byte即是描述数据的常用单位字节(即B)。说到这里要注意的是,常见的MB和Mb是不一样的。大写B一般指byte,而小写b一般指bit(即“位”)。1Byte=8bit。
不同的数据类型可以表示的范围和精度不同,我们应当根据需要来选择我们变量的数据类型。虽然话是这么说,但是因为一些原因,更多的时候,或者在难以确定哪种类型更合适的时候,我们会使用int。
这里的位数(bit),是二进制位,而不是十进制位。二进制本身并没有什么神秘的。我们常用的十进制,逢十进一,从右往左第n位上的数字m代表m个n-1的二次幂。
比如114514这个十进制数,换一个角度看它其实是1x10^5+1x10^4+4x10^3+5x10^2+1x10^1+1x10^0。
对于1010110这个二进制数,把前面的10换成2就懂了。正因为逢二进一,因此二进制只有两个数0和1。同样的道理,什么八进制、十六进制,甚至三进制十五进制都是同样的道理。不过由于我们还是习惯用阿拉伯数字表示数,因此到了十六进制我们会缺六个数,因此9之后的数字是由A到F来表示的(大小写通常不作区分)。
表示文字的类型
string是C#中用来表示字符串的类型。是很基本很常用的类型。无论是一个字符还是多个字符都可以使用string类型来表示。

char是另一个类型,char即character,它只能保存一个字符。字符字面量必须使用单引号。严格来说,C#的char是表示一个UTF-16字符。从string中获取单个char似乎很符合直觉,但是现在一般都会使用Unicode来表示各种语言的字符,各种字符的长度并不一样,如何断定“一个”字符也是一个问题。不同的编程语言处理如何从字符串里拿到“一个”字符的方式也不一样。
字面量
上面提到的表示数字和字符串的语法,实际上被称作字面量(literal,亦称字面值、直接量)。简单来说,字面量就是编程语言里面一种可以直接写出数据的值的特殊语法。就像数字来说,其实最终存在计算机中的数字肯定不是阿拉伯数字,但是我们可以以我们习惯的方式写出来,方便我们的书写和阅读。
在C#中使用不含小数点的阿拉伯数字序列表示的数会被识别为int,带小数点会被识别为double。而long和double类型也有其字面量,只需要在数字最后面分别加上L和D(大小写均可)。

如果不加后面的字母直接把1或者1.0赋值给float和double其实也是可以的,也就是发生了类型转换。但是把1L给整形变量可不行。
C#中的数字字面量除了表示常见的十进制数,还可以直接写出二进制和十六进制数。b和x大小写均可。b代表binary,x代表hex。

被广泛用于数据交换和各种配置文件的JSON,其全名是JavaScript对象记法(JavaScript Object Notation),它实际上是JavaScript语法的一部分(即所谓子集),它是JavaScript中的对象字面量的写法。对的,JavaScript是可以直接“写出”一个对象的。C#实际上也可以,类似的写法会产生一个匿名对象。
思考:数字?字符串?字符?

使用学过的WriteLine输出n和stringOfN,结果是否一样?可以把字符串给n,把数字给stringOfN吗?字符串和字符可以相互赋值吗?
输出n和stringOfN会得到相同的结果,字符E和字符串E也会输出相同的结果。实际上这是各个类型的ToString方法的功劳,WriteLine会根据各个不同类型的不同的ToString来把他们转换成字符串最终输出。如果你尝试把非数值的值给n,或者把数字给字符串,把字符给字符串等等。你会发现提示错误,无法将某某类型隐式地转换为某某类型。这是C#的类型机制。C#是强类型的语言,很多类型之间不会发生隐式类型转换,你需要使用某种方法把一种类型的值转换为另一种类型,否则C#编译器会检测到等号两边的数据类型不兼容(即无法相互转换并匹配)。从而引发错误。这是C#保证类型安全的措施之一。
是或不是——布尔类型
世界上一切只有两种结果的事情都可以使用布尔类型来表达。
是或不是,对与错,买得起还是买不起。
布尔类型的值同一时间只能取true或false中的一个值。

事实上不是所有编程语言表示布尔类型的两个值都是true或者false,其实你可以想一想,似乎用两个数字也能表达出对或错的概念。某些语言还会使用yes和no。
var——偷懒
var关键字同样用于声明变量。但是这个关键字本身不包含必要的类型信息,而是根据等号右边的值进行类型推导来确定类型。对于类型名称很复杂、一时难以确定类型、类型没有名字等情况下。我们使用var进行声明,从而省略了显式(explicitly,其实就是明确地的意思,但是中文的资料一般都爱写显式。其反义词implicitly,也就是隐含地,一般说成隐式地。)标注类型的过程。

它们分别是什么类型?
JavaScript程序员需要注意。这并不是代表C#是动态语言。C#的var更像C++的auto。var和auto变量一样,都在编译时可以确定,如果不能确定,那么就是编译时错误了。即使是将匿名对象赋值给一个用var声明的变量,它的类型也是编译时可知的,因为生成匿名对象时会生成一个匿名类。
思考:如果不给变量赋初值
前面写的几行代码中,我们声明变量时就给了它们一个值,那么如果不给它们一个初值,直接输出它们会发生什么呢?程序会出错吗?
答案是不会出错。这些类型都有它们各自的默认值。数值类型都是在数学上等于0的值。字符和字符串都是等价于空字符的值。
不变的量——常量
变量可以理解为“可变量”,那么有没有不可以变的量呢。当然是有的。
const关键字用于声明常量(constant)。常量只能被赋值一次,并且必须在声明时完成赋值,整个程序运行过程中,它都不会也不能被改变。
C++程序员注意,C#的const和C++中的有一些不一样的地方。C#中的const作用很单一,只能用于声明编译时常量。const在变量名前和类型前并没有区别,因为C#的const必须放在类型前面。

常量其实可以理解为一个只读的量。实际上C#中还有一个关键字readonly,正如其名,标注了readonly的变量是只读的。它和const有什么区别呢,区别在于readonly可以是自定义类型和类类型。所以有时候,readonly也被称为运行时常量。
试一下
尝试声明各种类型的变量并赋值,看看是否和预期的输出一样。
下一篇里,我们一起学习如何让计算机做它的本职工作:计算。

Ellsworth 1年前
下一篇——你的对象。全文空白,全剧终。
黛黛冬优子 [作者] 1年前
发布