4. bool类型
C#的 bool 类型用于包含bool值true或false,如表2-4所示。
表 2-4
|
名 称 |
CTS 类 型 |
值 |
|
bool |
System.Boolean |
true或false |
bool值和整数值不能相互转换。如果变量(或函数的返回类型)声明为bool类型,就只能使用值true或false。如果试图使用0表示false,非0值表示true,就会出错。
5. 字符类型
为了保存单个字符的值,C#支持char数据类型,如表2-5所示。
表 2-5
|
名 称 |
CTS 类 型 |
值 |
|
char |
System.Char |
表示一个16位的(Unicode)字符 |
虽然这个数据类型在表面上类似于C和C++中的char类型,但它们有重大区别。C++的char表示一个8位字符,而C#的char包含16位。其部分原因是不允许在char类型与8位byte类型之间进行隐式转换。
尽管8位足够编码英语中的每个字符和数字0~9了,但它们不够编码更大的符号系统中的每个字符(例如中文)。为了面向全世界,计算机行业正在从8位字符集转向16位的Unicode模式,ASCII编码是Unicode的一个子集。
char类型的字面量是用单引号括起来的,例如'A'。如果把字符放在双引号中,编译器会把它看作是字符串,从而产生错误。
除了把char表示为字符字面量之外,还可以用4位16进制的Unicode值(例如'\u0041'),带有数据类型转换的整数值(例如(char)65),或16进制数('\x0041')表示它们。它们还可以用转义序列表示,如表2-6所示。
表 2-6
|
转 义 序 列 |
字 符 |
|
\' |
单引号 |
|
\" |
双引号 |
|
\\ |
反斜杠 |
|
\0 |
空 |
|
\a |
警告 |
|
\b |
退格 |
|
\f |
换页 |
|
\n |
换行 |
|
\r |
回车 |
|
\t |
水平制表符 |
|
\v |
垂直制表符 |
C++开发人员应注意,因为C#本身有一个string类型,所以不需要把字符串表示为char类型的数组。
2.4.4 预定义的引用类型
C#支持两个预定义的引用类型,如表2-7所示。
表 2-7
|
名 称 |
CTS 类 |
说 明 |
|
object |
System.Object |
根类型,CTS中的其他类型都是从它派生而来的(包括值类型) |
|
string |
System.String |
Unicode字符串 |
1. object类型
许多编程语言和类结构都提供了根类型,层次结构中的其他对象都从它派生而来。C#和.NET也不例外。在C#中,object类型就是最终的父类型,所有内在和用户定义的类型都从它派生而来。这是C#的一个重要特性,它把C#与VB和C++区分开来,但其行为与Java非常类似。所有的类型都隐含地最终派生于System.Object类,这样,object类型就可以用于两个目的:
● 可以使用object引用绑定任何子类型的对象。例如,第5章将说明如何使用object类型把堆栈中的一个值对象装箱,再移动到堆中。对象引用也可以用于反射,此时必须有代码来处理类型未知的对象。这类似于C++中的void指针或VB中的Variant数据类型。
● object类型执行许多基本的一般用途的方法,包括Equals()、GetHashCode()、GetType()和ToString()。用户定义的类需要使用一种面向对象技术—— 重写(见第4章),提供其中一些方法的替代执行代码。例如,重写ToString()时,要给类提供一个方法,提供类本身的字符串表示。如果类中没有提供这些方法的实现代码,编译器就会使用object类型中的实现代码,它们在类中的执行不一定正确。
后面的章节将详细讨论object类型。
2. string类型
有C和C++开发经验的人员可能在使用C风格的字符串时不太顺利。C或C++字符串不过是一个字符数组,因此客户机程序员必须做许多工作,才能把一个字符串复制到另一个字符串上,或者连接两个字符串。实际上,对于一般的C++程序员来说,执行包装了这些操作细节的字符串类是一个非常头痛的耗时过程。VB程序员的工作就比较简单,只需使用string类型即可。而Java程序员就更幸运了,其String类在许多方面都类似于C#字符串。
C#有string关键字,在翻译为.NET类时,它就是System.String。有了它,像字符串连接和字符串复制这样的操作就很简单了:
string str1 = "Hello ";
string str2 = "World";
string str3 = str1 + str2; // string concatenation
尽管这是一个值类型的赋值,但string是一个引用类型。String对象保留在堆上,而不是堆栈上。因此,当把一个字符串变量赋给另一个字符串时,会得到对内存中同一个字符串的两个引用。但是,string与引用类型在常见的操作上有一些区别。例如,修改其中一个字符串,就会创建一个全新的string对象,而另一个字符串没有改变。考虑下面的代码:
using System;
class StringExample
{
public static int Main()
{
string s1 = "a string";
string s2 = s1;
Console.WriteLine("s1 is " + s1);
Console.WriteLine("s2 is " + s2);
s1 = "another string";
Console.WriteLine("s1 is now " + s1);
Console.WriteLine("s2 is now " + s2);
return 0;
}
}
其输出结果为:
s1 is a string
s2 is a string
s1 is now another string
s2 is now a string
换言之,改变s1的值对s2没有影响,这与我们期待的引用类型正好相反。当用值"a string"初始化s1时,就在堆上分配了一个string对象。在初始化s2时,引用也指向这个对象,所以s2的值也是"a string"。但是现在要改变s1的值,而不是替换原来的值时,堆上就会为新值分配一个新对象。s2变量仍指向原来的对象,所以它的值没有改变。这实际上是运算符重载的结果,运算符重载详见第5章。基本上,string类实现为其语义遵循一般的、直观的字符串规则。
字符串字面量放在双引号中("...");如果试图把字符串放在单引号中,编译器就会把它当作char,从而引发错误。C#字符串和char一样,可以包含Unicode、16进制数转义序列。因为这些转义序列以一个反斜杠开头,所以不能在字符串中使用这个非转义的反斜杠字符。而需要用两个反斜杠字符(\\)来表示它:
string filepath = "C:\\ProCSharp\\First.cs";
即使用户相信自己可以在任何情况下都记住要这么做,但键入两个反斜杠字符会令人迷惑。幸好,C#提供了另一种替代方式。可以在字符串字面量的前面加上字符@,在这个字符后的所有字符都看作是其原来的含义——它们不会解释为转义字符:
string filepath = @"C:\ProCSharp\First.cs";
甚至允许在字符串字面量中包含换行符:
string jabberwocky = @"'Twas brillig and the slithy toves
Did gyre and gimble in the wabe.";
那么jabberwocky的值就是:
'Twas brillig and the slithy toves
Did gyre and gimble in the wabe.






