C#数据类型
1. 什么是数据类型?
数据类型定义了变量可以存储的数据种类、占用内存的大小以及可以对变量执行的操作。C# 中的数据类型主要分为两类:
- 值类型 (Value Types):直接存储数据,如整数、浮点数、布尔值等。
- 引用类型 (Reference Types):存储数据的引用(内存地址),如字符串、数组、类等。
2. 值类型 (Value Types)
值类型变量直接在栈内存中存储实际数据。以下是常见的内置值类型:
2.1 整数类型
整数类型用于存储没有小数部分的数字。C# 提供多种整数类型,区别在于大小和是否支持负数:
类型 | 占用字节 | 范围 | 描述 |
---|---|---|---|
byte |
1 | 0 到 255 | 无符号 8 位整数 |
sbyte |
1 | -128 到 127 | 有符号 8 位整数 |
short |
2 | -32,768 到 32,767 | 有符号 16 位整数 |
ushort |
2 | 0 到 65,535 | 无符号 16 位整数 |
int |
4 | -2,147,483,648 到 2,147,483,647 | 有符号 32 位整数 |
uint |
4 | 0 到 4,294,967,295 | 无符号 32 位整数 |
long |
8 | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 | 有符号 64 位整数 |
ulong |
8 | 0 到 18,446,744,073,709,551,615 | 无符号 64 位整数 |
示例代码:
|
|
2.2 浮点类型
浮点类型用于存储带小数部分的数字,适用于需要高精度的场景:
类型 | 占用字节 | 范围 | 精度 |
---|---|---|---|
float |
4 | ±1.5e-45 到 ±3.4e38 | 7 位有效数字 |
double |
8 | ±5.0e-324 到 ±1.7e308 | 15-16 位有效数字 |
decimal |
16 | ±1.0e-28 到 ±7.9e28 | 28-29 位有效数字 |
注意:
float
需要在数字后加f
(如3.14f
)。decimal
需要加m
(如3.14m
),适合金融计算等高精度场景。
示例代码:
|
|
2.3 布尔类型
bool
:占用 1 字节,值只能是true
或false
。- 用于逻辑判断。
示例代码:
|
|
2.4 字符类型
char
:占用 2 字节,存储单个 Unicode 字符(用单引号''
表示)。
示例代码:
|
|
2.5 结构体 (Struct)
结构体是用户定义的值类型,包含多个字段。例如,System.DateTime
是一个结构体。
示例代码:
|
|
3. 引用类型 (Reference Types)
引用类型变量存储的是数据的内存地址,数据本身存储在堆内存中。常见的引用类型包括:
3.1 字符串 (String)
string
:表示不可变的 Unicode 字符序列。- 使用双引号
""
定义。
示例代码:
|
|
3.2 数组 (Array)
数组是固定大小的元素集合,元素类型必须一致。
示例代码:
|
|
3.3 类 (Class)
类是用户定义的引用类型,可以包含字段、属性、方法等。
示例代码:
|
|
3.4 对象 (Object)
object
是所有类型的基类,任何类型都可以转换为object
。- 使用时需注意装箱和拆箱(见下文)。
示例代码:
|
|
4. 值类型与引用类型的区别
特性 | 值类型 | 引用类型 |
---|---|---|
存储位置 | 栈内存 | 堆内存(引用在栈中) |
赋值行为 | 复制整个值 | 复制引用(指向同一对象) |
默认值 | 0 或相应类型的默认值 | null |
示例 | int , double , struct |
string , class , array |
示例代码(值类型与引用类型的赋值行为):
|
|
5. 类型转换
C# 中类型转换分为以下几种:
5.1 隐式转换
低精度类型到高精度类型的自动转换,无需显式声明。
示例代码:
|
|
5.2 显式转换
高精度类型到低精度类型需要强制转换,可能丢失数据。
示例代码:
|
|
5.3 使用 Convert
类
System.Convert
类提供多种类型转换方法。
示例代码:
|
|
5.4 使用 Parse
和 TryParse
Parse
:将字符串转换为指定类型,若失败抛出异常。TryParse
:尝试转换,若失败返回false
,不抛异常。
示例代码:
|
|
6. 装箱与拆箱 (Boxing and Unboxing)
- 装箱:将值类型转换为
object
或接口类型,存储到堆内存。 - 拆箱:从
object
类型转换回值类型。
示例代码:
|
|
注意:装箱和拆箱会影响性能,尽量避免在性能敏感的代码中使用。
7. 可空类型 (Nullable Types)
值类型默认不能为 null
,但可通过可空类型(如 int?
)支持 null
值。
示例代码:
|
|
可空值类型简写:
int?
等价于Nullable<int>
。
8. 动态类型 (Dynamic Type)
dynamic
类型允许在运行时确定类型,绕过编译时类型检查。适用于与动态语言交互或未知类型的场景。
示例代码:
|
|
注意:使用 dynamic
会降低代码可读性和性能,建议谨慎使用。
9. 字面量 (Literals)
字面量是直接在代码中书写的常量值,用于初始化变量或表示特定值。C# 支持多种类型的字面量,并允许使用前缀或后缀来指定数据类型或进制。
9.1 常见字面量类型
- 整数字面量:
- 十进制:
123
- 十六进制:
0x7B
(以0x
开头) - 二进制:
0b01111011
(以0b
开头,C# 7.0+ 支持) - 后缀:
L
(long
)、UL
(ulong
)、U
(uint
)。
- 十进制:
- 浮点字面量:
- 普通浮点:
3.14
- 科学计数法:
3.14e2
(表示 3.14 × 10² = 314) - 后缀:
f
(float
)、d
(double
)、m
(decimal
)。
- 普通浮点:
- 字符字面量:
'A'
或'\u0041'
(Unicode 字符)。 - 字符串字面量:
- 普通字符串:
"Hello"
- 逐字字符串:
@"C:\Path"
(忽略转义字符)。 - 插值字符串:
$"Value: {x}"
(C# 6.0+)。
- 普通字符串:
- 布尔字面量:
true
、false
。 - 空字面量:
null
(仅限引用类型或可空值类型)。
示例代码:
|
|
9.2 字面量后缀和前缀
- 后缀明确数据类型:
123L
:long
123.45f
:float
123.45m
:decimal
- 前缀指定进制:
0x
:十六进制0b
:二进制(C# 7.0+)
10. 进制转换
C# 提供了多种方法在不同进制(如十进制、十六进制、二进制)之间转换数值。
10.1 使用字面量直接表示
如上所述,可以直接使用 0x
或 0b
前缀定义十六进制或二进制值。
示例代码:
|
|
10.2 使用 Convert.ToString
转换到指定进制
Convert.ToString
方法可以将数字转换为指定进制的字符串表示。
示例代码:
|
|
10.3 使用 Convert.ToInt32
等从字符串解析
可以将字符串形式的其他进制数解析为十进制。
示例代码:
|
|
10.4 格式化输出
使用字符串格式化控制进制输出。
示例代码:
|
|
11. 高级主题:元组 (Tuple)
C# 7.0 引入了元组,允许将多个值组合为一个轻量级的数据结构。
示例代码:
|
|
12. 实践建议
- 选择合适的数据类型:
- 使用
int
或double
进行常规计算。 - 使用
decimal
进行金融计算。 - 使用
string
处理文本。
- 使用
- 避免不必要的装箱/拆箱:尽量使用泛型(如
List<T>
)代替ArrayList
。 - 善用可空类型:在需要表示“无值”时使用
int?
等。 - 小心类型转换:使用
TryParse
避免异常。 - 动态类型谨慎使用:仅在必要时使用
dynamic
,如与 COM 对象交互。 - 字面量和进制转换:
- 使用
0x
和0b
前缀简化十六进制和二进制输入。 - 使用
Convert.ToString
和Convert.ToInt32
进行进制转换。
- 使用
13. 示例程序
以下是一个综合示例,展示多种数据类型、字面量和进制转换的用法:
|
|