当前位置: 首页 > news >正文

C#.NET struct 全解析:什么时候该用值类型?

简介

struct是 值类型(Value Type),用于封装一组相关的数据。
与类(class)相比,结构体通常更轻量,适用于小型、短生命周期的对象。

⚡ 关键特点:

  • 存储在 栈(stack)上(也可能嵌套在堆中,但本质仍是值类型)。

  • 按值传递(赋值/参数传递时会复制整个结构)。

  • 无需垃圾回收(GC),生命周期由作用域决定。

  • 可包含字段、属性、方法、构造函数、运算符重载等。

基本语法

publicstructPoint{publicintX;publicintY;publicPoint(intx,inty){X=x;Y=y;}publicvoidMove(intdx,intdy){X+=dx;Y+=dy;}}

使用:

Pointp1=newPoint(3,4);p1.Move(1,2);Console.WriteLine($"{p1.X},{p1.Y}");// 4, 6

内存模型与分配

分配场景存储位置说明
局部变量最典型场景,生命周期由方法作用域决定
作为类字段包含在类对象内部,但值本身在堆内存中
数组元素数组本身在堆上,每个元素紧密排列

即使struct位于堆中(例如类字段、数组元素),它仍然是值类型,操作时是按值复制。

与 class 的区别

特性class(引用类型)struct(值类型)
内存分配堆(GC 管理)栈/堆中嵌入
传递方式按引用传递(复制引用)按值传递(复制整个对象)
默认构造函数可定义无参/有参系统提供无参构造,用户不能定义
继承支持继承/虚方法不能继承,只能实现接口
空值(null)可以为 null不可为 null(除非Nullable<T>
装箱/拆箱不涉及赋值给object时会装箱
性能分配慢(GC)分配快,生命周期短时更高效

构造函数与初始化

默认构造函数
  • 所有结构体都有一个隐式的无参构造函数,将所有字段初始化为 默认值(如0null)。

  • 用户不能显式定义无参构造函数(C# 10开始支持,但有限制)。

自定义构造函数

可以定义有参构造函数,但必须初始化所有字段。

publicPoint(intx,inty){X=x;// 必须全部赋值Y=y;}
结构体的成员

结构体可以包含:

  • 字段(Field

  • 属性(Property

  • 方法(Method

  • 事件(Event

  • 运算符重载

  • 静态成员

  • 构造函数(但无参构造受限)

不支持:

  • 继承其他类/结构体(只能实现接口)。

  • 明确的析构函数(~Destructor)。

值类型的特性

按值传递

结构体赋值时会复制整个值:

Pointp1=newPoint(1,2);Pointp2=p1;// 复制p2.X=99;Console.WriteLine(p1.X);// 1,不受 p2 修改影响
装箱/拆箱

赋值给object或接口时,会将结构体复制到堆中:

Pointp=newPoint(1,2);objectobj=p;// 装箱:复制到堆Pointp2=(Point)obj;// 拆箱:从堆复制回栈

装箱/拆箱会带来性能开销,应尽量避免频繁发生。

不可变结构体(Immutable struct)

为了避免复制带来的副作用,结构体推荐设计为不可变:

publicreadonlystructPoint{publicintX{get;}publicintY{get;}publicPoint(intx,inty)=>(X,Y)=(x,y);}
实现接口
publicinterfaceIDrawable{voidDraw();}publicstructCircle:IDrawable{publicdoubleRadius{get;}publicPointCenter{get;}publicCircle(doubleradius,Pointcenter){Radius=radius;Center=center;}publicvoidDraw(){Console.WriteLine($"Drawing circle at{Center}with radius{Radius}");}publicdoubleArea=>Math.PI*Radius*Radius;}
structRectangle:IEquatable<Rectangle>{publicintWidth,Height;publicboolEquals(Rectangleother){returnWidth==other.Width&&Height==other.Height;}publicoverrideboolEquals(objectobj)=>objisRectangleother&&Equals(other);publicoverrideintGetHashCode()=>HashCode.Combine(Width,Height);}varr1=newRectangle{Width=10,Height=20};varr2=newRectangle{Width=10,Height=20};Console.WriteLine(r1.Equals(r2));// 输出: True
运算符重载示例
structPoint{publicintX,Y;publicPoint(intx,inty){X=x;Y=y;}publicstaticPointoperator+(Pointa,Pointb){returnnewPoint(a.X+b.X,a.Y+b.Y);}publicoverridestringToString()=>$"({X},{Y})";}varp1=newPoint(1,2);varp2=newPoint(3,4);varsum=p1+p2;Console.WriteLine(sum);// 输出: (4, 6)

结构体的新特性

readonly struct
  • 表示完全不可变。

  • 编译器强制所有字段为readonly

  • 防止无意修改。

publicreadonlystructVector{publicreadonlydoubleX;publicreadonlydoubleY;}
ref struct
  • 只能在栈上分配。

  • 用于高性能场景,如Span<T>

record struct

值类型的 记录类型,支持内建的值比较、with表达式。

publicrecordstructPoint(intX,intY);varp1=newPoint(1,2);varp2=p1with{X=3};// 基于值的复制

高级用法

与模式匹配结合使用
publicstructRGBColor{publicbyteR;publicbyteG;publicbyteB;publicRGBColor(byter,byteg,byteb){R=r;G=g;B=b;}publicvoidDeconstruct(outbyter,outbyteg,outbyteb){r=R;g=G;b=B;}}classProgram{staticstringGetColorName(RGBColorcolor){returncolorswitch{(255,0,0)=>"Red",(0,255,0)=>"Green",(0,0,255)=>"Blue",(255,255,255)=>"White",(0,0,0)=>"Black",_=>"Unknown"};}staticvoidMain(){RGBColorred=newRGBColor(255,0,0);Console.WriteLine(GetColorName(red));// 输出: Red}}

适用场景

✅ 适合:

  • 轻量级、小数据对象(坐标、颜色、矩形、数值容器等)。

  • 高性能计算(避免GC开销)。

  • 频繁创建销毁的对象。

❌ 不适合:

  • 对象非常大(复制开销高)。

  • 需要继承层次。

  • 需要引用语义(共享同一对象)。

如果类型大小超过 16 字节,且频繁传递,建议使用class而不是struct

实战示例

高性能点计算
publicreadonlystructPoint{publicreadonlydoubleX;publicreadonlydoubleY;publicPoint(doublex,doubley)=>(X,Y)=(x,y);publicdoubleDistance(Pointother)=>Math.Sqrt(Math.Pow(X-other.X,2)+Math.Pow(Y-other.Y,2));}voidDemo(){Pointp1=new(1,2);Pointp2=new(4,6);Console.WriteLine(p1.Distance(p2));// 5}
  • GC压力。

  • 值传递保证线程安全。

总结

特性说明
类型值类型(Value Type)
内存分配栈分配或嵌入堆中
继承不能继承其他类/结构体,只能实现接口
构造函数系统提供无参构造;用户可定义有参构造
默认初始化所有字段自动初始化为默认值
传递方式按值传递(复制整个对象)
典型场景小型数据对象(Point、Color)、高性能计算
高级特性readonly structref structrecord struct
设计建议尽量保持不可变,避免装箱,避免过大对象
http://www.cnnetsun.cn/news/124365.html

相关文章:

  • 如何快速生成XML站点地图:SEO优化的终极指南
  • 32、Linux 技术资源与操作指南
  • 高效智能重命名:APK Installer自定义应用名称实战指南
  • ImageToSTL终极指南:零基础将图片秒变3D打印模型
  • Android音频转发实战:解决手机声音投屏电脑的三大痛点
  • Windows第三方酷安客户端终极完整快速使用指南
  • NSFC数据查询工具:快速获取国家自然科学基金信息的终极指南
  • Denoising Diffusion PyTorch:从零开始掌握图像生成核心技术
  • SD-WebUI模型下载器:国内用户免代理高速下载Civitai模型完整指南
  • 3步快速上手ScratchJr-Desktop:儿童编程启蒙的最佳选择
  • 5步搞定多域名邮件配置:Mail-in-a-Box一站式管理指南
  • 如何用MPV_lazy打造你的专属智能播放器
  • 如何评估RAG系统好坏?Kotaemon内置评测工具介绍
  • ComfyUI_IPAdapter_plus终极解决方案:三步根除ClipVision模型加载故障
  • 百度网盘秒传工具实用指南:5分钟学会高效文件管理
  • 3步快速部署OpenProject:从零搭建高效协作平台
  • 15、深入了解Hyper - V:嵌套虚拟化、虚拟机创建与配置
  • 22、Windows Server与Nano Server的容器配置及Docker使用指南
  • 如何快速制作精简版Windows 11系统:完整教程指南
  • 5分钟掌握vmrc:让虚拟机管理变得像聊天一样简单
  • 32、菜单与工具栏开发指南
  • 轻松搞定多域名邮件管理:告别繁琐配置的终极指南
  • 41、GTK+ 额外小部件与打印功能实现
  • 大麦网智能抢票助手完整使用指南:告别手动抢票烦恼
  • 43、GTK+ 额外小部件与应用实践
  • Minecraft数据编辑指南:NBTExplorer新手实战教程
  • COMET翻译评估:颠覆传统的人工智能评分革命
  • 赛马娘汉化插件深度体验:解锁全新游戏世界
  • ComfyUI ControlNet Aux 深度与法线预处理终极指南:5分钟从2D图像提取3D信息
  • 抖音批量下载神器深度解析:从入门到精通的全能指南