C#中类和结构体的对比

区别

C# 中的类(Class)和结构体(Struct)是两种不同的数据类型,它们在很多方面有相似之处,但也存在一些关键的区别:

  1. 继承

    • 类可以继承其他类或实现接口。

    • 结构体不能继承其他结构体或类,也不能被继承,但可以实现接口。

  2. 默认访问修饰符

    • 类的成员默认是非公开的(private),需要显式指定访问级别。

    • 结构体的所有成员默认是公开的(public),并且不能是私有的。

  3. 实例化

    • 类的实例是在堆上分配的,可以通过 new 关键字来创建。

    • 结构体的实例可以在堆上或栈上分配,但通常在栈上分配,且不需要 new 关键字。

  4. 可变性

    • 类的实例可以是可变的,即其状态可以在创建后被修改。

    • 结构体是值类型,其状态在创建后通常被认为是不可变的,尽管可以通过引用传递来修改其成员。

  5. 垃圾回收

    • 类的实例由垃圾回收器管理,因此涉及到垃圾回收的开销。

    • 结构体由于通常在栈上分配,通常不会有垃圾回收的开销,但当作为对象的一部分或分配在堆上时,其生命周期结束时也需要垃圾回收。

  6. 使用场景

    • 类通常用于表示具有复杂行为的对象,需要继承或多态性的场景。

    • 结构体通常用于表示简单的数据结构,如简单的数据容器或轻量级的数据类型。

  7. 方法和属性

    • 类和结构体都可以有方法、属性、索引器、事件和构造函数。

  8. 静态成员

    • 类和结构体都可以有静态成员,但静态构造函数只适用于类。

  9. 装箱和拆箱

    • 结构体作为值类型,当需要与对象类型交互时,可能会涉及到装箱(boxing)和拆箱(unboxing)操作,这会带来性能开销。

ref struct介绍

在 C# 7.2 及更高版本中,引入了一个新的结构体类型,称为 ref structref struct 是一种特殊的结构体,它有一些独特的特性和限制:

  1. 堆分配ref struct 必须在堆上分配不能在栈上分配。这意味着你不能直接将 ref struct 作为方法参数或返回类型,也不能作为局部变量使用,除非它们是通过引用传递的

  2. 引用传递ref struct 实例必须通过引用传递,即使它们在堆上分配。这保证了对 ref struct 的任何修改都是可见的。

  3. 不能包含引用类型字段ref struct 不能包含引用类型的字段,因为它们不能被垃圾回收。这有助于避免不必要的垃圾回收开销,因为 ref struct 不会被垃圾回收器跟踪。

  4. 不能实现接口:由于 ref struct 必须在堆上分配,它们不能实现接口。这是因为接口的实现可能需要引用类型的特性,这与 ref struct 的设计原则相冲突。

  5. 不能被继承ref struct 不能被继承,因为继承可能会引入引用类型的复杂性。

  6. 使用场景ref struct 主要用于性能敏感的场景,特别是在与非托管代码交互时。它们可以用于避免不必要的复制,特别是在需要频繁传递大型数据结构时。

ref struct 是一种高级特性,通常只在特定的性能优化场景中使用。它们提供了一种方式来避免值类型的一些限制,如栈分配和复制开销,但同时也带来了一些限制,如不能实现接口和不能被继承。在使用 ref struct 时,你需要仔细考虑这些特性和限制,以确保它们适合你的用例。

ref return

在 C# 7.2 引入了 ref return 特性,它允许方法返回对局部变量的引用。这在之前版本的 C# 中是不可能的,因为局部变量在方法调用结束后就不再存在了。通过 ref return,你可以返回一个引用,允许调用者修改返回的局部变量的值。

使用 ref return 时,需要注意以下几点:

  1. 返回局部变量的引用ref return 允许方法返回一个引用到局部变量的引用,调用者可以通过这个引用修改原始数据。

  2. 返回的局部变量必须在方法调用结束后仍然存在:为了满足这个要求,返回的局部变量通常被分配在 stackalloc 内存中,或者作为 ref struct 的成员。

  3. 调用者可以通过返回的引用修改数据:由于返回的是引用,调用者对返回值的任何修改都会反映在原始数据上。

  4. 使用 ref 关键字:在方法的返回类型前使用 ref 关键字来指示该方法返回一个引用。

  5. 调用方法时也需要使用 ref:当调用返回 ref 的方法时,你需要使用 ref 关键字来接收返回的引用。

  6. 示例

    private ref int GetCount()
    {int count = 1; // 局部变量return ref count; // 返回局部变量的引用
    }
    ​
    void IncrementCount()
    {ref int count = ref GetCount();count += 1; // 修改原始的局部变量
    }

  7. 使用场景ref return 可以在需要优化性能的场景中使用,尤其是在避免不必要的数据复制时。例如,在处理大型数据结构或与非托管代码交互时,ref return 可以提供一种有效的方式来传递和修改数据。

  8. 限制:由于 ref return 改变了局部变量的作用域,因此在使用时需要小心,以避免意外的行为或内存问题。

ref return 是 C# 中一个强大的特性,它提供了更多的灵活性来处理数据的传递和修改。然而,由于它改变了局部变量的生命周期和作用域,因此在实际应用中需要谨慎使用。

通过new创建的结构体是放在堆上

在 C# 中,结构体(Struct)通常不需要使用 new 关键字来创建实例。结构体是值类型,它们的实例可以在栈上自动分配,并且可以通过直接赋值来创建。例如:

Point p = new Point(); // 错误,结构体通常不使用new
Point p2 = new Point(10, 20); // 正确,但不是推荐的方式
Point p3 = { X = 10, Y = 20 }; // 推荐的方式,使用初始化器
Point p4 = new Point { X = 10, Y = 20 }; // 另一种推荐的方式

然而,如果你确实想要使用 new 关键字来创建结构体的实例,C# 也允许这样做,但这并不是推荐的做法。使用 new 创建结构体实例时,实际上是在堆上分配内存,这会导致额外的性能开销,因为堆分配需要垃圾回收器的介入。此外,使用 new 创建的值类型实例在某些情况下可能会引起混淆,因为它们的行为更接近于引用类型。

在大多数情况下,你应该避免使用 new 来创建结构体的实例,而是使用默认构造函数或初始化器来初始化它们。如果你需要在堆上创建结构体的实例,可以使用 Activator.CreateInstance 方法,但这通常不是必要的,除非有特定的需求。

// 使用Activator.CreateInstance在堆上创建结构体实例
Point p5 = (Point)Activator.CreateInstance(typeof(Point));

总的来说,结构体作为值类型,其设计初衷是为了在栈上高效地分配和使用,而不是在堆上。因此,使用 new 创建结构体实例并不是 C# 中的常见做法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/386761.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Synchronized的锁升级过程是怎样的?

文章目录 一、Synchronized的使用1、修饰实例方法2、修饰静态方法3、修饰代码块4、总结: 二、Monitor1、Java对象头1.1 32 位虚拟机的对象头1.2 64位虚拟机的对象头 2、Mark Word 结构3、Moniter4、Synchronized 字节码5、轻量级锁6、锁膨胀7、自旋优化8、偏向锁9、…

命令行使用ADB,不用root,完美卸载小米预装软件

ADB安装与运行 install java 下载安装 注意选择JDK17以上版本 https://www.oracle.com/java/technologies/downloads/#jdk22-windows 选择中间的安装文件下载 编辑系统变量 C:\Program Files (x86)\Java\jdk-22 C:\Program Files (x86)\Java\jdk-22\bin 把C:\Progra…

K210视觉识别模块学习笔记7:多线程多模型编程识别

今日开始学习K210视觉识别模块: 图形化操作函数 亚博智能 K210视觉识别模块...... 固件库: canmv_yahboom_v2.1.1.bin 训练网站: 嘉楠开发者社区 今日学习使用多线程、多模型来识别各种物体 这里先提前说一下本文这次测试实验的结果吧:结果是不太成…

视频去水印免费电脑版 pdf压缩在线免费网页版 pdf压缩在线免费 简单工具软件详细方法步骤分享

消除视频中的恼人水印,是许多视频编辑爱好者的常见需求。在这篇文章中,我们将探讨几种视频去水印的技巧,在数字化时代,视频和图片的传播越来越方便,但随之而来的水印问题也让人头疼。本文将为您详细介绍视频剪辑去水印…

捕获会自动消失的消息提示弹窗

如上图,我们会在一些场景碰到会自动消失的消息提示弹窗,一般存在个3-5秒,我们在做UI断言时,需要监测这个弹窗是否会出现,就需要去捕获这个弹窗的位置 我们打开浏览器的开发者模式(F12),找到源码(Sources) …

探索 Redis 不同集群架构的性能与应用

1. 引言 Redis的集群配置成为了提高数据可靠性和服务可用性的关键。本文将带领大家了解Redis的四种主要集群架构,并重点分析哨兵模式和Redis Cluster架构和优势。 2. Redis的四种集群架构 2.1 单实例Redis 使用单个 Redis 实例提供服务。适用于小规模应用&#…

MiniExcel:.NET中处理Excel的高效方案

在.NET开发环境中,处理Excel文件是一项常见的任务,无论是数据导入、导出还是报表生成。传统的解决方案可能存在性能瓶颈或功能限制。MiniExcel作为一个现代、高效的库,为.NET开发者提供了一个强大的工具来简化Excel操作。本文将介绍MiniExcel…

爬虫程序在采集亚马逊站点数据时如何绕过验证码限制?

引言 在电商数据分析中,爬虫技术的应用日益广泛。通过爬虫技术,我们可以高效地获取大量的电商平台数据,这些数据对于市场分析、竞争情报、价格监控等有着极其重要的意义。亚马逊作为全球最大的电商平台之一,是数据采集的重要目标…

【技术升级】Docker环境下Nacos平滑升级攻略,安全配置一步到位

目前项目当中使用的Nacos版本为2.0.2,该版本可能存在一定的安全风险。软件的安全性是一个持续关注的问题,尤其是对于像Nacos这样的服务发现与配置管理平台,它在微服务架构中扮演着核心角色。随着新版本的发布,开发团队会修复已知的…

【解决】ubuntu20.04 root用户无法SSH登陆问题

Ubuntu root用户无法登录的问题通常可以通过修改‌SSH配置文件和系统登录配置来解决。 修改SSH配置文件 sudo vim /etc/ssh/sshd_config 找到 PermitRootLogin 设置,并将其值更改为 yes 以允许root用户通过SSH登录 保存并关闭文件之后,需要重启SSH服务…

【HarmonyOS】实现矩形上下拖动、动态拖拽修改高度

简介 实现一个矩形块上下拖动,并且可以拖动边缘定位点改变矩形块高度。实现效果如下: 代码 Entry Component struct Rec_Page {State penOffsetY: number 0;State offsetX: number 0State offsetY: number 0State positionX: number 0State posi…

Microsoft 官网免费下载安装正版官方增强版 office LSTC (长期支持版) 包含 visio , access

1.进入下方网址: https://www.microsoft.com/en-us/download/details.aspx?id49117 下载文件: officedeploymenttool_17126-20132.exe 现在看到下载链接可能失效了,但是下述步骤任然正确。需要下载文件的可以私信发送。 2.进入下方网址…

家具购物小程序的设计

管理员账户功能包括:系统首页,个人中心,用户管理,家具分类管理,家具新品管理,订单管理,系统管理 微信端账号功能包括:系统首页,家具新品,家具公告&#xff0…

filament 初使用记录

安装初始化 一、环境准备 官网要的 我安装的 二、下载安装 安装laravel composer create-project --prefer-dist laravel/laravel 项目名称 10.*导入 filament composer require filament/filament注册 filament 管理面板 php artisan filament:install --panels初始化…

vue3前端开发-小兔鲜项目-登录组件的开发表单验证

vue3前端开发-小兔鲜项目-登录组件的开发表单验证&#xff01;现在开始写登录页面的内容。首先这一次完成基础的首页按钮点击跳转&#xff0c;以及初始化一些简单的表单的输入验证。后期还会继续完善内容。 1&#xff1a;首先还是准备好login页面的组件代码内容。 <script …

MySQL基础练习题7-销售分析

题目&#xff1a;报告 2019年春季 才售出的产品。即 仅 在 2019-01-01 &#xff08;含&#xff09;至 2019-03-31 &#xff08;含&#xff09;之间出售的商品。 准备数据 分析数据 方法一&#xff1a;group by having 第一步&#xff1a;先找到要求的列 第二步&#xff1…

CAN转PROFINET网关

型号&#xff1a;TCA-152 &#xff08;上海泗博自动化技术有限公司产品&#xff09; 基本说明&#xff1a;TCA-152可实现 PROFINET网络与CAN网络之间的数据通信。网关在PROFINET网络作为从站&#xff0c;CAN端支持CAN2.0A/CAN2.0B协议&#xff0c;支持对CAN帧进行过滤处理。 …

python 图片转文字、语音转文字、文字转语音保存音频并朗读

一、python图片转文字 1、引言 pytesseract是基于Python的OCR工具&#xff0c; 底层使用的是Google的Tesseract-OCR 引擎&#xff0c;支持识别图片中的文字&#xff0c;支持jpeg, png, gif, bmp, tiff等图片格式 2、环境配置 python3.6PIL库安装Google Tesseract OCR 3、安…

谷粒商城实战笔记-65-商品服务-API-品牌管理-表单校验自定义校验器

文章目录 1&#xff0c;el-form品牌logo图片自定义显示2&#xff0c;重新导入和注册element-ui组件3&#xff0c;修改brand-add-or-update.vue控件的表单校验规则firstLetter 校验规则sort 校验规则 1&#xff0c;el-form品牌logo图片自定义显示 为了在品牌列表中自定义显示品…