3.1 C#程序是一组类型声明
如果广泛地描述C和C++程序源代码的特征,可以说C程序是一组函数和数据类型,C++程序是一组函数和类,然而C#程序是一组类型声明。
- C#程序或DLL的源代码是一组类型声明。
- 对于可执行程序,类型声明中必须有一个包含Main方法的类。
- 命名空间一种把相关的类型声明分组并命名的方法。既然程序是一组相关的类型声明,那么通常会把程序声明在创建的命名空间内部。
3.2 类型是一种模板
把类型想象成一个用来创建数据结构的模板。模板本身并不是数据结构,但它详细说明了由该模板构造的对象的特征。
类型由下面的元素定义:
- 名称
- 用于保存数据成员的数据结构
- 一些行为及约束条件。
3.3 实例化类型
从某个类型模板创建实际的对象,称为实例化该类型。
- 通过实例化类型而创建的对象被称为类型的对象或类型的实例。这两个术语可以互换。
- 在C#程序中,每个数据项都是某种类型的实例。这些类型可以是语言自带的,可以是BCL或其它库提供的,也可以是程序员定义的。
3.4 数据成员和函数成员
数据成员:保存了与这个类的对象或类本身相关的数据。
函数成员:执行代码。函数成员定义类型的行为。
3.5 预定义类型
C#提供了15种预定义类型。包括13种简单类型和2种非简单类型。
所有预定义类型的名称都由全小写的字母组成。预定义的简单类型包括:
- 11种数值类型
- 不同长度的有符号和无符号整数类型
- 浮点类型float和double
- 一种称为decimal的高精度小数类。与float和double不同,decimal类型可以准确地表示分数。decimal类型常用于货币的计算。
- 一种Unicode字符类型char
- 一种布尔类型bool。 true / false 与C和C++不同,在C#中的数值不具有布尔意义。
两种非简单类型
- string,它是一个Unicode字符数组。
- object,它是所有其他类型的基类。
3.6 预定义类型的补充
所有预定义类型都直接映射到底层的.NET类型。C#的类型名称就是.NET类型的别名,所以使用.NET的类型名称也能很好地符合C#语法,不过并不鼓励这样做。在C#程序中,应该疍使用C#类型名称而不是.NET类型名称。
\x0000
名称 | 含义 | 范围 | .NET框架类型 | 默认值 |
---|---|---|---|---|
sbyte | 8位有符号整数 | -128~127 | System.SByte | 0 |
byte | 8位无符号整数 | 0~255 | System.Byte | 0 |
short | 16位有符号整数 | -32768~32767 | System.Int16 | 0 |
ushort | 16位无符号整数 | 0~65535 | System.UInt16 | 0 |
int | 32位有符号整数 | -2147483648~2147483647 | System.Int32 | 0 |
uint | 32位无符号整数 | 0~4294967295 | System.UInt32 | 0 |
long | 64位有符号整数 | -9223372036854775808 ~9223372036854775807 | System.Int64 | 0 |
ulong | 64位无符号整数 | 0~18446744073709551615 | System.UInt64 | 0 |
float | 单精度浮点数 | 1.5*10(-45)~3.4*10(38) | System.Single | 0.0f |
double | 双精度浮点数 | 5*10(-324)~1.7*10(308) | System.Double | 0.0d |
bool | 布尔型 | true false | System.Boolean | false |
char decimal | Unicode字符串 小数类型的有效数字精度为38位 | U+0000~U+ffff +/-1.0*10(28)~+/-7.0*10(28) | System.Char System.Decimal |
名称 | 含义 | .NET框架类型 |
---|---|---|
object | 所有其他类型的基类 | System.Object |
string | Unicode字符序列 | System.String |
3.7 用户定义类型
6种类型可以由用户自己创建
- 类类型(class)
- 结构类型(struct)
- 数组类型(array)
- 枚举类型(enum)
- 委托类型(delegate)
- 接口类型(interface)
类型通过类型声明创建,类型声明包含以下信息:
- 要创建的类型的种类。
- 新类型的名称
- 对类型中每个成员的声明(名称和规格)。array和 delegate类型除外,它们不含有命名成员。
3.8 栈和堆
运行中的程序使用两个内存区域来存储数据:栈和堆。
栈
系统接管所有的栈操作。作为程序员,不需要显示地对它做任何事情。
栈是一个内存数组,是一个LIFO(last-in first-out,后进先出)的数据结构。栈存储几种类型的数据:
- 某些类型变量的值;
- 程序当前的执行环境;
- 传递给方法的参数;
栈的特征
- 数据只能从栈的顶端插入和删除
- 把数据放到栈顶称为入栈(push)
- 从栈顶删除数据称为出线(pop)
堆
堆是一块内存区域,在堆里可以分配大块的内存用于存储某类型的数据。与栈不同,堆里的内存可以任意顺序存入和移除。
虽然程序可以在堆里保存数据,但并不能显式地删除它们。CLR的自动GC(Garbage Collector,垃圾收集器)在判断出程序的代码将不会再访问某数据项时,自动清除无主的堆对象。
3.9 值类型和引用类型
数据项的类型定义了存储数据需要的内存大小、组成该类型的数据成员以及类型能执行的函数。类型还决定了对象在内在中的存储位置——栈或堆。
类型被分为两种:值类型和引用类型,这两种类型的对象在内存中的存储方式不同。
- 值类型只需要一段单独的内存,用于存储实际的数据。
- 引用类型需要两段内存:
- 第一段存储实际的数据,它总是位于堆中。
- 第二段是一个引用,指向数据在堆中的存放位置。
对于值类型,数据存放在栈里。对于引用类型,实际数据存放在堆里而引用存放在栈里。
对于引用类型的任何对象,它所有的数据成员都存放在堆里,无论它们是值类型还是引用类型。
C#的值类型和引用类型
值类型:sbyte
byte
short
ushor t
int
unit
long
ulong
float
double
char
decimal
bool
struct
e num
引用类型:object
string
class
interface
delegate
array
3.10 变量
名称 | 类型的成员 | 描述 |
本地变量 | 否 | 在方法的作用域保存临时数据 |
字段 | 是 | 保存和类型相关的数据 |
参数 | 否 | 用于从一个方法到另一个方法传递数据的临时变量 |
数据元素 | 是 | 用于保存临时的或类型相关的数据 |
变量声明
变量在使用之前必须声明。变量声明定义了变量,并完成两件事:
- 给变量命名,并为它关联一种类型;
- 让编译器为它分配一块内存。
变量初始化语句
除声明变量的名称和类型以外,声明还能把它的内存初始化为一个明确的值。
变量初始化语句(variable)由一个等号后面跟一个初始值组成。
自动初始化
一些类型的变量如果在声明时没有初始化语句,那么会被自动设为默认值,而另一些则不能。没有自动初始化为默认值的变量在程序为它同仁之前包含未定义值。
变量类型 | 存储位置 | 自动初始化 | 用途 |
---|---|---|---|
本地变量 | 栈或者栈和堆 | 否 | 用于函数成员内部的本地计算 |
类字段 | 堆 | 是 | 类的成员 |
结构字段 | 栈或堆 | 是 | 结构的成员 |
参数 | 栈 | 否 | 用于把值传入或传出方法 |
数组元素 | 堆 | 是 | 数组的成员 |
多重变量声明
可以把多个变量声明在一条单独的声明语句中。
- 多重变量声明中的变量必须类型相同。
- 变量名必须用逗号分隔,可以在变量名后包含初始化语句。