值类型和引用类型分类
预定义内置类型
| 分类 | 包含类型 |
|---|---|
| 值类型(基础数值 / 布尔 / 字符) | 有符号整数:sbyte、short、int、long无符号整数: byte、ushort、uint、ulong浮点 / 高精度: float、double、decimal布尔: bool、字符: char |
| 引用类型(内置引用) | object(所有类型基类)、string、dynamic |
用户自定义类型
| 分类 | 类型 |
|---|---|
| 值类型 | struct(结构体)、enum(枚举) |
| 引用类型 | class、interface、delegate、array(数组) |
如上节课说的,引用类型的数据,必定存储在堆中,但是值类型的数据有可能存储在堆,有可能在栈
引用类型的引用部分,有可能存储在堆,也又可能存储在栈。
存储在堆还是存储在栈,要看这个值类型变量和引用类型的引用部分,是属于类型的数据成员,还是函数里面的局部变量。
四类变量
| 变量类型 | 定义与作用 |
|---|---|
| 局部变量 Local variable | 方法内部临时数据,不属于类型成员; 保存在栈中 不会自动初始化 |
| 字段 Field | 类 / 结构体绑定的数据,属于类型成员; 类字段存储在堆中 结构体字段随结构体存储; 自动初始化 |
| 参数 Parameter | 方法传参临时变量,不属于类型成员; 保存在栈中 不会自动初始化 |
| 数组元素 Array element | 数组内的单个数据; 全部存堆 自动初始化 |
关于什么叫自动初始化,也就是程序员不给这个变量一个初始值,编译器会自动赋给一个初始值的。
更简单地概况
| 变量类型 | 存储位置 | 是否自动初始化 |
|---|---|---|
| 局部变量 | 栈 / 栈 + 堆 | 否 |
| 类字段 | 堆 | 是 |
| 结构体字段 | 栈 / 堆 | 是 |
| 方法参数 | 栈 | 否 |
| 数组元素 | 堆 | 是 |

变量声明
格式:类型 变量名;
int var2;Code language: C# (cs)
上面代码,是声明一个变量,上面代码主要完成两件事:
- 告诉编译器var2是一个int类型的变量,名称是var2.
- 编译器会在内存中分配内存空间,至于是在堆还是在栈,要看情况。这个变量是局部变量,是参数,还是字段等等。

变量初始化器(Initializer)
语法:类型 变量名 = 初始值;
示例:int var2 = 17;
初始化器是编译器的一个工具,它帮我们进行一些变量的初始化,但是有一些变量是必须程序员在代码里面初始化的,有一些变量则程序员可用不初始化它,交给变量初始化器帮我们完成初始化。
局部变量无初始化时值未定义,编译报错,无法直接使用;
字段、数组元素等自动初始化变量会赋予默认值:数值 0、引用null。
读者看例子:
class Program
{
static void Main(string[] args)
{
int times = 100;
Person person = new Person();
}
}
class Person
{
public int age;
}
Code language: C# (cs)
这个例子很简单,Main函数中,定义了一个值类型的变量time,和一个应用类型的变量person,引用类型里面有一个字段age。
age没有给初始值。二time是我们程序员给了初始化值。
这时候编译是正常的。

如果我们的time不给赋初值100.改成如下

直接出现红色波浪线,连编译都不能编译了。
强行编译会提示错误

error list窗口会列出错误信息

注意:需要在代码中去使用这个times变量才行,如果没有调用,则还是不会报错的。还是可用编译的。
class Program
{
static void Main(string[] args)
{
int times;
Person person = new Person();
}
}
Code language: C# (cs)
如果是类型里面的字段,例如:下面Person里面的age,没有给初始化值,但是如果编译运行是可以的。
class Program
{
static void Main(string[] args)
{
int times = 100;
Console.WriteLine(times);
Person person = new Person();
Console.WriteLine(person.age);
}
}
class Person
{
public int age;
}
Code language: C# (cs)

读者会发现,正常输出了0,也就是age是类里面的成员字段,不给初始化值的时候,初始化器会给它一个默认值,对于int类型默认值是0,不同的类型的默认值是不同的。
多变量同句声明
- 同一行只能声明相同类型变量;
- 逗号分隔变量名,可混合初始化 / 未初始化变量;
- 禁止一行混合多种数据类型。
// 合法
int var3 = 7, var4, var5 = 3;
double var6, var7 = 6.52;
// 非法!混合 int 与 float
int var8, float var9;
Code language: JavaScript (javascript)
使用变量值
直接书写变量名即可读取内存中存储的值:
Console.WriteLine("{0}", var2);Code language: JavaScript (javascript)
