C# 学习之路(类型、存储和变量)
如果泛泛的描述 C 和 C++ 程序源代码的特征,可以说 C 程序是一组函数和数据类型,C++ 是一组函数和类,而 C# 程序是一组类型的声明。
命名空间是一种将相关的类型声明分组并命名的方法。因为程序是一组相关的类型声明,所以通常在你创建的命名控件内部声明程序类型。
C# 程序是一组类型的声明,那么学习 C# 就是学习如何创建和使用类型。
可以把类型当成一个用来创建数据结构的模板。模板本身并不是数据结构,但它详细说明了由该模板构造的对象特征。
类型由下面的元素定义:
- 名称
- 保存数据成员的数据结构
- 行为及约束条件
// 个人理解 class node // 名称 { int a,b; // 成员数据 void fun() // 行为约束 { Console.WriteLine($"{a}, {b}"); } } // 书本图示 ---------------------- |名称 short| 结构 2字节| ---------------------- | 行为 16位整数 | ---------------------- ---------------------- |名称 int | 结构 4字节| ---------------------- | 行为 32位整数 | ----------------------
从某个类型模板创建实际的对象,称为实例化该类型。
通过实例化类型而创建的对象被称为类型的对象或者类型的实例。
short a1,a2,a3; // a1、a2、a3成为short的实例 int b1,b2,b3; // b1、b2、b3成为int的实例
像 short 、int 和 long 这样的类型称为简单类型,这种类型只能存储一个数据项。
其它的类型可以存储多个数据项,列如:数组(array)类型就可以存储多的同类型的数据项,这样的数据项被称为数组元素。通过索引来引用这些元素。
成员的类别
有一些的类型可以包含许多不同的数据项,这些类型中的数据项个体成为成员,与数组中使用数字来引用成员不同,这些成员有独特的名字。
两种成员:数据成员和函数成员
数据成员:保存了与这个类的对象或整个类相关的数据。
函数成员:执行代码。函数成员定义类型的行为。
// 类型为 XYZ de 一些数据成员和函数成员 XYZ { datamem1; // 数据成员 datamem2; // 数据成员 F1(){ ExecuttableCode // 函数成员 } F1(){ ExecuttableCode // 函数成员 } }
C# 提供了 16 种预定义类型,其中包括 13 种简单类型和 3 种非简单类型。
所有预定义类型的名称都由全小写的字母组成。预定义的简单类型包含以下 3 种
11 种数值类型
不同长度的有符号和无符号整数类型
浮点数类型 float 和 double
decimal 高精度小数类型,与 float 和 double 不同,decimal 类型可以准确地表示分数。
一种 Unicode 字符类型 char
一种 bool 类型,bool 类型表示布尔值,必须为 true 或 false。(C# 中的数值类型不具有布尔含义)
3 种非简单类型如下
- string,Unicode 字符数组
- object,这是所有其他类型的基类
- dynamic,使用动态语言编写的程序集时使用
除了 C# 提供的 16 种预定义类型,还可以创建自己的用户定义类型。有 6 种类型可以由用户创建
- 类 类型(class)
- 结构类型(struct)
- 数组类型(array)
- 枚举类型(enum)
- 委托类型(delegate)
- 接口类型(interface)
通过类型声明创建类型,类型声明包含以下信息:
- 要创建的类型的种类
- 新类型的名称
- 对类型中每个成员的声明(名称和规格),array 和 delegate 类型除外(这两类不含有命名成员)
class AA // 类型 class 名称 AA { int a,b; // 成员声明 double c,d; }
运行中程序使用两个内存区域存储数据:栈和堆
- 栈
栈是一个内存数组,是一个 LIFO(Last In First out,后进先出)的数据结构。栈存储几种类型的数据:
- 某些类型变量的值
- 程序当前的执行环境
- 传递给方法的参数
- 堆
堆是一块内存区域,在堆里可以分配大块的内存用于存储某种类型的数据对象。和栈不同的是,堆里的内存能够以任意顺序存入和移除。
程序在堆里保存数据,但并不能显示的删除它们。CLR 的自动垃圾收集器在判断程序的代码将不会再访问某一数据项时,会自动清除无主的堆对象。
数据项的类型(int、double、short 等)定义了存储数据需要的内存大小及组成该成员类型的数据成员。类型还决定了在内存中的存储位置——栈或堆
类型被分为两类:值类型和引用类型,这样两种类型的对象在存储方式上不同。
(C# 图解教程第五版(P39)表4-3是错误的)
- 值类型只需要一段独立的内存,用于存储实际的数据。(数据存储在栈里)
- 引用类型需要两段内存(实际数据存放在堆里,引用存放在栈里)
- 第一段存储实际的数据,它总是位于堆中
- 第二段是一个引用,指向数据在堆中的存放位置
变量表示程序执行时存储在内存中的数据,C# 提供 4 种变量。
名称 描述 本地变量 在方法的作用域保存临时数据,不是类型成员 字段 字段是在类(class)或结构体(struct)中直接声明的任意类型的变量。 字段是其包含类型的成员 参数 用于从一个方法到另一个方法传递数据的临时变量,不是类型的成员 数组元素 同类数据项构成的有序集合的一个成员,可以为本地变量,也可为类型的成员
- 变量声明
变量使用前必须声明,变量声明定义了变量,并完成两件事:
- 给变量命名,并为它关联一种类型
- 让编译器为它分配一块内存
int var1; 类型 值
- 变量初始化
除了声明变量的名称和类型外,声明还能把它的内存初始化为一个明确的值。
int va1 = 10;
- 自动初始化
一些类型的变量如果在声明时没有初始化,那么会被自动设置为默认值,而另一些则不能。
变量类型 存储位置 是否自动初始化 用途 本地变量 栈、栈和堆 否 用于函数成员内部的本地计算 类字段 堆 是 类的成员 结构字段 栈、堆 是 结构的成员 参数 栈 否 用于把值传入或传出方法 数组元素 堆 是 数组的成员
- 多变量声明
- 声明的变量类型必须相同
- 变量名之间必须用逗号分隔,可以在变量名的后面包含初始化语句
int var1 = 1, var2 = 2; double var3 = 0.1, var4;
dynamic
类型是一种静态类型,但类型为dynamic
的对象会跳过静态类型检查
可空类型允许创建可以标记为有效或无效的值类型变量,这样就可以在使用它之前确定值得有效性.普通得值类型称为非可空类型.