在C#编程中,数据类型是构建程序的基础。无论是简单的变量存储,还是复杂的数据结构,都离不开对数据类型的正确理解和使用。C#是一种强类型语言,这意味着每个变量和对象都必须有明确的类型,并且在编译时会进行严格的类型检查。
本文将全面介绍C#的数据类型,包括值类型(Value Types)和引用类型(Reference Types),并深入探讨它们的存储方式、转换规则以及在实际开发中的应用。此外,我们还会涉及可空类型(Nullable Types)、类型转换以及动态类型(dynamic)等高级话题。
1. C#数据类型概述
C#的数据类型可以分为两大类:
-
值类型(Value Types):直接存储数据,变量包含实际值。
-
引用类型(Reference Types):存储数据的引用(内存地址),变量指向堆(Heap)中的数据。
此外,C#还支持特殊类型(如dynamic
、var
)和可空类型(Nullable Types),以适应不同的编程需求。
2. 值类型(Value Types)
值类型的变量直接存储数据,而不是引用。它们在栈(Stack)上分配内存,具有较快的访问速度,但通常用于存储较小的数据。
2.1 基本数值类型
整数类型
类型 | 位数 | 范围 |
---|---|---|
byte | 8 | 0 到 255 |
sbyte | 8 | -128 到 127 |
short | 16 | -32,768 到 32,767 |
ushort | 16 | 0 到 65,535 |
int | 32 | -2,147,483,648 到 2,147,483,647 |
uint | 32 | 0 到 4,294,967,295 |
long | 64 | -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 |
ulong | 64 | 0 到 18,446,744,073,709,551,615 |
示例:
int age = 30;
long population = 7_900_000_000; // 使用下划线提高可读性
浮点类型
类型 | 位数 | 精度 | 范围 |
---|---|---|---|
float | 32 | ~6-9位小数 | ±1.5×10⁻⁴⁵ 到 ±3.4×10³⁸ |
double | 64 | ~15-17位小数 | ±5.0×10⁻³²⁴ 到 ±1.7×10³⁰⁸ |
decimal | 128 | 28-29位小数 | ±1.0×10⁻²⁸ 到 ±7.9×10²⁸ |
示例:
float pi = 3.14f; // 必须加 'f' 后缀
double distance = 1.495978707e8; // 科学计数法
decimal price = 19.99m; // 适合金融计算,加 'm' 后缀
2.2 布尔类型(bool)
bool
类型只有两个值:true
或 false
,常用于条件判断。
示例:
bool isActive = true;
if (isActive)
{
Console.WriteLine("系统已激活");
}
2.3 字符类型(char)
char
表示单个Unicode字符,用单引号 ' '
定义。
示例:
char grade = 'A';
char newLine = '\n'; // 转义字符
2.4 结构体(struct)
结构体是用户自定义的值类型,适用于轻量级数据。
示例:
struct Point
{
public int X;
public int Y;
}
Point p = new Point { X = 10, Y = 20 };
2.5 枚举(enum)
枚举用于定义一组命名的常量。
示例:
enum Weekday { Monday, Tuesday, Wednesday, Thursday, Friday }
Weekday today = Weekday.Monday;
3. 引用类型(Reference Types)
引用类型的变量存储的是数据的引用(内存地址),实际数据存储在堆(Heap)上。
3.1 类(class)
类是C#中最常用的引用类型,包括:
-
object
(所有类型的基类) -
string
(不可变的Unicode字符串) -
用户自定义类
示例:
class Person
{
public string Name;
public int Age;
}
Person p = new Person { Name = "Alice", Age = 25 };
3.2 字符串(string)
string
是特殊的引用类型,具有不可变性(每次修改都会创建新对象)。
示例:
string name = "Bob";
name += " Smith"; // 创建新字符串
3.3 数组
数组是固定大小的集合,可以是一维或多维。
示例:
int[] numbers = new int[5] { 1, 2, 3, 4, 5 };
string[,] matrix = new string[2, 2] { { "A", "B" }, { "C", "D" } };
3.4 接口(interface)
接口定义了一组方法,由类实现。
示例:
interface IShape
{
double Area();
}
class Circle : IShape
{
public double Radius;
public double Area() => Math.PI * Radius * Radius;
}
3.5 委托(delegate)
委托类似于函数指针,用于实现回调机制。
示例:
delegate void LogMessage(string message);
void PrintToConsole(string msg) => Console.WriteLine(msg);
LogMessage logger = PrintToConsole;
logger("Hello, World!");
4. 特殊类型
4.1 var(隐式类型)
var
让编译器自动推断变量类型。
示例:
var name = "Alice"; // 编译为 string
var age = 30; // 编译为 int
4.2 dynamic(动态类型)
dynamic
绕过编译时类型检查,运行时解析。
示例:
dynamic obj = 10;
obj = "Now I'm a string!"; // 合法,但可能引发运行时错误
5. 可空类型(Nullable Types)
值类型默认不能为 null
,但可以使用 Nullable<T>
或 ?
语法使其可空。
示例:
int? nullableInt = null;
double? nullableDouble = 3.14;
if (nullableInt.HasValue)
{
Console.WriteLine(nullableInt.Value);
}
6. 类型转换
6.1 隐式转换(自动)
小范围类型 → 大范围类型(如 int
→ long
)。
示例:
int i = 100;
long l = i; // 自动转换
6.2 显式转换(强制)
大范围类型 → 小范围类型(可能丢失数据)。
示例:
double d = 3.14;
int i = (int)d; // i = 3(截断小数部分)
6.3 Parse 和 TryParse
将字符串转换为其他类型。
示例:
string input = "123";
int num = int.Parse(input); // 可能抛出异常
bool success = int.TryParse(input, out int result); // 安全转换
7. 总结
-
值类型(
int
,double
,struct
)存储在栈上,访问速度快。 -
引用类型(
class
,string
,array
)存储在堆上,变量存储的是引用。 -
可空类型允许值类型为
null
,适用于数据库交互。 -
类型转换包括隐式、显式、
Parse
和TryParse
。 -
var
和dynamic
提供更灵活的变量声明方式。
理解C#的数据类型是编写高效、健壮代码的关键。希望本文能帮助你更好地掌握这些概念!