C#基础数据类型

C# 里到底有哪些数据类型?它们之间有什么区别?什么时候该用 int​,什么时候该用 long?这篇就来聊聊 C# 的基础数据类型体系,帮你理清分类、存储方式和使用场景。

  1. 值类型 vs 引用类型:核心区别是什么,如何选择
  2. 常用数据类型一览:整数、浮点、布尔、字符、字符串、对象
  3. 类型转换与注意事项:隐式转换、显式转换、装箱拆箱的陷阱

一、C# 数据类型体系

1.1 类型分类概述

C# 的类型系统分为三大类:

类型分类 存储位置 示例 特点
值类型 栈(Stack) int​, double​, bool​, struct​, enum 直接包含数据,复制时拷贝整个值
引用类型 堆(Heap) string​, class​, array​, delegate​, object 存储对象的引用,复制时拷贝引用(地址)
指针类型 非托管内存 int* 仅用于 unsafe 上下文,一般开发不常用

划重点: 值类型变量直接保存数据,引用类型变量保存对象的地址(引用)。赋值时值类型是值拷贝 ,引用类型是引用拷贝(两个变量指向同一对象)。

1.2 值类型详解

值类型包括:简单类型枚举类型结构体类型可空值类型

常用简单值类型
类型 关键字 字节 范围
整型 sbyte 1 -128 ~ 127
无符号 byte 1 0 ~ 255
短整型 short 2 -32,768 ~ 32,767
无符号短整型 ushort 2 0 ~ 65,535
整型(默认) int 4 -2.1e9 ~ 2.1e9
无符号整型 uint 4 0 ~ 4.2e9
长整型 long 8 -9.2e18 ~ 9.2e18
无符号长整型 ulong 8 0 ~ 1.8e19
浮点型 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 位精度,货币计算)
布尔 bool 1 true​ / false
字符 char 2 单个 Unicode 字符(U+0000 ~ U+FFFF)

常见坑: float​ 精度只有 7 位,大量累加或金融计算时请用 decimal,否则会出现意想不到的精度丢失。

结构体(struct)

结构体是自定义值类型,适用于表示轻量级数据(如坐标、RGB颜色)。

csharp 复制代码
public struct Point
{
    public int X;
    public int Y;

    public Point(int x, int y) => (X, Y) = (x, y);
}

代码解析:

  1. struct 关键字:声明一个值类型,实例化时分配在栈上(或作为其他类型的字段内联存储)。
  2. 构造函数:struct 中允许定义带参构造函数,但不能定义无参构造函数(C# 10 之前)。
  3. 字段:可以直接公开字段(但不推荐,通常用属性)。值类型的字段会直接存储值。

1.3 引用类型详解

引用类型包括:字符串数组接口委托对象

类型 关键字 说明
对象 object 所有类型的基类,可引用任何类型
字符串 string 不可变的 Unicode 字符串序列
动态 dynamic 运行时类型检查,跳过编译时类型检查
class 引用类型,支持继承、多态
字符串细节
csharp 复制代码
string s1 = "Hello";
string s2 = s1;
s2 = "World";
Console.WriteLine(s1); // 输出 "Hello"(不变)

代码解析:

  1. string 不可变性 :每次修改字符串(如 s2 = "World")都会在堆上创建新对象,原对象不变。
  2. 引用拷贝s2 = s1 只是拷贝引用,两个变量指向同一对象。但后续 s2 指向新对象后,s1 不受影响。
  3. 性能提示 :大量字符串拼接应使用 StringBuilder,避免频繁创建新对象。

二、类型转换

2.1 隐式转换

发生条件:从小范围大范围转换,且数值不会有损失。

csharp 复制代码
int i = 10;
long l = i;          // int → long,安全,隐式
float f = i;         // int → float,安全,隐式
double d = f;        // float → double,安全,隐式

2.2 显式转换(强制类型转换)

发生条件:可能丢失精度或范围超限,需要显式告诉编译器。

csharp 复制代码
double d = 123.456;
int i = (int)d;      // 显式转换,小数部分被截断
Console.WriteLine(i); // 输出 123(丢失精度)

long l = 3000000000;
int i2 = (int)l;     // 超出 int 范围,会溢出(checked 模式下抛异常)

常见坑: 使用显式转换时建议用 Convert​ 类或 TryParse​,或者放在 checked 块中捕获溢出。

2.3 装箱与拆箱

装箱(boxing):值类型 → object 或接口类型。拆箱(unboxing):逆过程。

csharp 复制代码
int num = 42;
object obj = num;     // 装箱:在堆上分配对象,拷贝值
int numBack = (int)obj; // 拆箱:从堆对象拷贝回栈

代码解析:

  1. 装箱 :会在堆上分配一个 object 对象,将值类型数据拷贝进去,性能开销较大(分配+拷贝)。
  2. 拆箱:检查对象类型是否匹配,然后拷贝回值类型,同样有性能开销。
  3. 避免策略 :使用泛型(List<T>)代替 ArrayList,减少装箱拆箱。

划重点: 在性能敏感代码中,装箱拆箱是隐形杀手。多用泛型、避免把值类型频繁赋值给 object


三、选择数据类型的指南

场景 推荐类型 原因
普通整数计数 int 平衡大小和性能,默认整数类型
索引/遍历数组 int​ 或 long 数组长度通常不超 int 范围
数据库 ID(可能超大) long 分布式系统 ID 可能超过 21 亿
浮点运算(图形/物理) float 精度要求不高,节省带宽
科学计算/精度要求高 double 默认浮点类型
货币/财务计算 decimal 精确到小数点后 28 位
短文本 string C# 标准字符串

| 不可变值对象 | struct​ | 小体积、免 GC 分配 |

| 可能需要 null | 可空值类型(int?​)或 string? | 表示"无值"语义更清晰 |

最后

数据类型看似基础,但很多运行时 Bug 都源于对类型转换、装箱拆箱、引用拷贝的理解不够透彻。写代码时多问自己一句:这个变量是值类型还是引用类型?赋值后另一个变量会受影响吗?养成习惯,能避开一堆坑。

对于新手,遇到奇怪的"对象被修改了"问题,十有八九是引用类型赋值导致共享了同一个对象。记得用 Clone()或深拷贝来隔离。

相关推荐
唐青枫2 小时前
C#.NET YARP 跨域配置详解:网关统一处理 CORS
c#·.net
程序leo源5 小时前
Qt信号与槽深度详解
c语言·开发语言·数据库·c++·qt·c#
yoyo_zzm10 小时前
四大编程语言对比:C/C++/C#/PHP
c++·c#·php
weixin_4280053010 小时前
C#调用 AI学习从0开始-第1阶段(基础与工具)-第4天CoT思维链学习
开发语言·学习·ai·c#·cot
政沅同学11 小时前
C# TCP通讯(客户端)
网络·tcp/ip·c#
思麟呀11 小时前
在C++基础上理解CSharp-3
开发语言·c++·c#
rockey6271 天前
AScript如何实现LINQ语法
sql·c#·.net·linq·script·eval·expression
xiaoshuaishuai81 天前
C# CDN加速与离线包优化PowerSetting慢问题
开发语言·windows·spring·c#
烈焰猩猩1 天前
【无标题】
c#