论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
ToB门户
了解全球最新的ToB事件
博客
Blog
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
应用中心
搜索
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
账号登录
立即注册
找回密码
用户名
Email
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
qidao123.com技术社区-IT企服评测·应用市场
»
论坛
›
软件与程序人生
›
后端开发
›
.Net
›
.NET 结构体
.NET 结构体
小秦哥
论坛元老
|
2024-12-27 19:11:36
|
显示全部楼层
|
阅读模式
楼主
主题
1687
|
帖子
1687
|
积分
5061
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
我们都知道结构体struct,在大量创建、引用的场景下相比类class能提升很大性能。本文介绍下如何正确使用struct
struct定义
1 struct Point
2 {
3 public float X;
4 public float Y;
5 }
6
7 class Rect
8 {
9 public Point Position;
10 }
11
12 Rect rect = new Rect();
复制代码
上述代码中,rect的Position字段并没有分配到栈上,反而是和Rect的实例一起被分配到了托管堆中。除此之外,装箱也会导致结构体实例分配到托管堆:
1 Point point = new Point();
2 object obj = point; // 装箱,结构体转移到托管堆
复制代码
所以假如由于性能要求或者别的原因想限定struct只分配到栈上的话,可以添加ref:
1 ref struct Point
2 {
3 public float X;
4 public float Y;
5 }
复制代码
这种情况下,struct关键字前添加ref是指将结构体声明为只能在栈上分配的结构体,对于这种结构体,任何大概将其转移到托管堆的行为都将被制止(比方在引用类型中定义ref结构体字段,或者进行装箱操作):
1 class Rect
2 {
3 public Point Position; // 错误,Position会随着Rect实例转移到托管堆
4 }
5
6 Point point = new Point();
7 object obj = point; // 错误,point会被装箱到托管堆
复制代码
别的,ref声明的struct可以继续作为字段在新struct内声明:
1 ref struct PointNew
2 {
3 public Point Point; // 允许,因为XPoint同样保证了栈上分配
4 }
复制代码
还可以声明只读的ref结构体:
1 readonly ref struct PointNew
2 {
3 public Point Point; // 允许,因为XPoint同样保证了栈上分配
4 }
复制代码
使用struct
1. 结构体作为参数传递
1 Point p = new Point();
2 TestAdd(ref p);
3
4 void TestAdd(ref Point point)
5 {
6 point.X += 1;
7 }
复制代码
假如不是只传值而是需要变更数据,需要添加ref,否则TestAdd中point只会作为原来p的副本天生一个新结构体。那最终p中的X值还是初始值0。ref我们都熟悉了,值类型假如作为参数输入后,外部同步修改也是使用ref
2. 结构体存储大小
看下面这段代码,输出结构体在栈上所需的内存大小:
1 [StructLayout(LayoutKind.Auto)]
2 struct TestStorage
3 {
4 public byte A;
5 public int B;
6 public byte C;
7 public byte D;
8 public byte E;
9 }
10 // 输出
11 unsafe
12 {
13 Debug.WriteLine(sizeof(TestStorage));
14 }
复制代码
上面输出的值是12。我们聊下内存布局:
1)Sequential:顺序布局,按字段的声明顺序布局,是默认行为
2)Auto:自动布局,自动分列字段顺序以用最小的空间来储存字段
3)Explicit:显式布局,手动指定字段地址的偏移
一般来说,byte是1,int是4。
在不添加[StructLayout(LayoutKind.Auto)]标记时,由于需要内存对齐,字段B是4,那内存大小就需要以4+4+4=12来分配,前面4存储字段A 1的内存,后面4存储字段CDE一共3的内存大小
添加[StructLayout(LayoutKind.Auto)]后,内存对齐,只需要4+4=8的内存大小
我们使用Struct场景主要有以下使用场景:
一般是某类数据使用较多、有较大的内存题目 - 对于不需要频繁分配和释放的大量小对象,可以使用结构体减少堆内存的压力
现有类对象创建采取过于频繁,性能有较大损耗 - 可以使用结构体,减少对象创建、垃圾采取的开销
结构体适合用于封装简单的数据,比方坐标点(Point)、复数(Complex Number)、时间段(TimeSpan)等
参考文章:
结构类型 - C# reference | Microsoft Learn
Struct 和 Class 的区别以及使用场景_struct和class使用场景-CSDN博客
出处:
http://www.cnblogs.com/kybs0/
让学习成为习惯,假设明天就有巨大机会等着你,你准备好了么本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文连接,否则保存追究法律责任的权利。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
继续阅读请点击广告
回复
使用道具
举报
0 个回复
倒序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
回帖后跳转到最后一页
发新帖
回复
小秦哥
论坛元老
这个人很懒什么都没写!
楼主热帖
Python教程(5)——Python的第一个程序 ...
Kubernetes(k8s)安装以及搭建k8s-Das ...
网易云信实时视频直播在TCP数据传输层 ...
〖Python接口自动化测试实战篇⑤〗- 接 ...
java递归简介说明
liunx速记
海量监控数据处理如何做,看华为云SRE ...
从 Stream 到 Kotlin 再到 SPL
开发一个二方包,优雅地为系统接入ELK ...
那些年用过的机械键盘
标签云
国产数据库
集成商
AI
运维
CIO
存储
服务器
快速回复
返回顶部
返回列表