C#类型基础Part1-值类型与引用类型
C#类型基础Part1-值类型与引用类型
- 参考资料
- 前言
- 值类型
- 引用类型
- 装箱和拆箱
参考资料
- 《.NET之美–.NET关键技术深入与解析》
前言
C#中的类型一共分为两类,一类是值类型(Value Type),一类是引用类型(Reference Type)。值类型和引用类型是以它们在计算机内存中是如何被分配来划分的。值类型包括了 结构 和 枚举,引用类型则包括了 类、接口、委托 等。还有一种特殊的值类型,称为简单类型,比如byte、int等,这些简单类型实际上是BCL基类库类型的别名。比如,声明一个int类型,实际上是声明一个 System.Int32 结构类型。因此,在 Int32 类型中定义的方法或属性,都可以在int类型上调用,比如:
123.Equals(2);
所有的值类型都隐式地继承自 System.ValueType 类型(注意 System.ValueType 本身是一个类类型)。之所以说是“隐式地”,是因为在C#代码中,是看不到这个继承关系的,这个关系只有通过MSIL代码才能看到。 System.ValueType 类型和所有的引用类型都继承自 System.Object 基类。
C#不支持多重继承,因为结构已经隐式地继承自ValueType,所以结构不支持继承
说明:
栈(stack)是一种 后进先出的数据结构,在内存中,变量会被分配在栈上来进行操作。堆(heap)是用于为==引用类型的实例(对象)==分配空间的内存区域,在堆上创建一个对象,会将对象的地址传给栈上的变量(反过来叫变量指向此对象,或者变量引用此对象)。
值类型
当声明一个值类型的变量的时候,变量本身包含了值类型的全部字段,该变量会被分配在线程堆栈(Thread Stack)上。
假如有下面这个值类型,代表了直线上的一点:
public struct ValPoint{public int x;public ValPoint(int x){this.x=x;}
}
当在程序中声明一个变量:
ValPoint vPoint1;
vPoint1.x=10;
Console.WriteLine(vPoint1.x);//输出10
上面代码中,因为变量已经包含了值类型的所有字段,所以已经可以进行操作,并且只有对变量进行操作(vPoint1.x=10
),才会进行入栈。对变量进行操作,实际上是一系列入栈、出栈操作。
如果将ValPoint改为引用类型class,则会出现编译错误:使用了未赋值的局部变量“vPoint1”。除此之外,引用类型在运行时经常会抛出NullReferenceException
异常。
如果不对vPoint1.x进行赋值,直接写Console.WriteLine(vPoint1.x)
,则会出现编译错误:使用了可能为赋值的字段x
。这是因为.NET的一个约束:所有的元素使用前都必须初始化。比如下面语句也会引发这个错误:
int i;
Console.WriteLine(i);
虽然结构类型变量本身不需要像类一样使用new操作符创建一个实例(其本身就相当于一个实例),但如果要使用它的内部成员,则要在使用前对它进行赋值。结构还有一个特性:调用结构上的方法前,需要对其所有字段进行赋值。 修改ValPoint:
public struct ValPoint{public int x;public void Blank(){}
}
那么下面的代码将会发生编译错误:
ValPoint vPoint1;
vPoint1.Blank();//使用了未赋值的变量vPoint1
Console.WriteLine(vPoint1);//使用了未赋值的变量vPoint1
解决上述问题可以通过这样一种方式:编译器隐式地为结构类型创建无参数的构造函数。在这个构造函数中会对结构成员进行初始化,所有的值类型成员被赋予0或者相当于0的值,所有的引用类型被赋予null值。(因此,Struct类型不可以自行声明无参数的构造函数)。所以,可以通过隐式声明的构造函数去创建一个ValPoint类型变量:
ValPoint vPoint1=new ValPoint();
Console.WriteLine(vPoint1.x);//输出0
引用类型
当声明一个引用类型变量,并使用new操作符创建引用类型实例的时候,该引用类型的变量会被分配到线程栈上,变量保存了位于堆上的引用类型的实例的内存地址。变量本身不包含任何类型所定义的数据。如果仅仅声明一个变量,但不使用new操作符,由于在堆上还没有创建类型的实例,因此,变量值为null,即不指向任何对象。
如果有这样一个类,它依然代表直线上的一点:
public class RefPoint{public int x;public RefPoint(int x){this.x=x}public RefPoint(){}
}
当仅仅写下
RefPoint rPoint1;
它会在线程栈上创建一个不包含任何数据,也不指向任何对象(不包含内存地址)的变量。
而当使用new操作符时:
rPoint1=new RefPoint(1)
则会完成下面几件事:
- 在应用程序堆上创建一个引用类型对象的实例,并分配内存地址
- 自动传递该实例的引用给构造函数。(正因为如此,才可以使用
this
来访问这个实例) - 调用该类型的构造函数。
- 返回该实例的引用(内存地址),赋值给人Point1变量
装箱和拆箱
简单来说,装箱就是将一个值类型转换为等价的引用类型。它的过程分为这样几步:
- 在堆上为新生成的对象实例分配内存。该对象实例包含数据,但没有名称。
- 将栈上值类型变量的值复制到堆上的对象中。
- 将堆上创建的对象的地址返回给引用类型变量。
装箱实例代码如下:
int i=1;
Object boxed=i;
Console.WriteLine("Boxed Point:"+boxed);
拆箱则是将一个已装箱的引用类型转换为值类型:
int i=1;
Object boxed=i;
int j;
j=(int)boxed;
Console.WriteLine("UnBoxed Point: " + j);
需要注意的是:拆箱操作需要显示声明拆箱后转换的类型。它分为两步来完成
- 获取已装箱的对象的地址。
- 将值从堆上的对象中复制到堆栈上的值变量中。
可见,装箱和拆箱需要反复在堆上进行操作,因此,在程序中应该尽量避免无意义的装箱和拆箱。
相关文章:
C#类型基础Part1-值类型与引用类型
C#类型基础Part1-值类型与引用类型 参考资料前言值类型引用类型装箱和拆箱 参考资料 《.NET之美–.NET关键技术深入与解析》 前言 C#中的类型一共分为两类,一类是值类型(Value Type),一类是引用类型(Reference Type)…...
被上市公司预判的EPS增速分析
EPS增速对二级市场投资和估值有着很显著的影响,上市公司显然也知道这一点。对于想要做市值管理的上市公司来说,调节EPS增速比调节EPS更加有效。因此《穿透财报:读懂财报中的逻辑与陷阱》中的作者在第四章正式提出了二级市场财务分析中的额动态…...

快速入门了解Ajax
博客主页:音符犹如代码系列专栏:JavaWeb关注博主,后期持续更新系列文章如果有错误感谢请大家批评指出,及时修改感谢大家点赞👍收藏⭐评论✍ Ajax的初识 意义:AJAX(Asynchronous JavaScript and…...

FPGA开发——呼吸灯的设计
一、原理 呼吸灯的原理主要基于PWM(脉冲宽度调制)技术,通过控制LED灯的占空比来实现亮度的逐渐变化。这种技术通过调整PWM信号的占空比,即高电平在一个周期内所占的比例,来控制LED灯的亮度。当占空比从0%逐渐变化到1…...

【数据结构】二叉树链式结构——感受递归的暴力美学
前言: 在上篇文章【数据结构】二叉树——顺序结构——堆及其实现中,实现了二叉树的顺序结构,使用堆来实现了二叉树这样一个数据结构;现在就来实现而二叉树的链式结构。 一、链式结构 链式结构,使用链表来表示一颗二叉树…...

开始尝试从0写一个项目--后端(三)
器材管理 和员工管理基本一致,就不赘述,展示代码为主 新增器材 表设计: 字段名 数据类型 说明 备注 id bigint 主键 自增 name varchar(32) 器材名字 img varchar(255) 图片 number BIGINT 器材数量 comment VARC…...
2024年7月解决Docker拉取镜像失败的实用方案,亲测有效
在Ubuntu 16.04、Debian 8、CentOS 7系统中,若遇到Docker拉取镜像失败的问题,以下是一些亲测有效的解决方案: 配置加速地址 首先,创建Docker配置目录:sudo mkdir -p /etc/docker然后,编辑daemon.json文件…...

基于内容的音乐推荐网站/基于ssm的音乐推荐系统/基于协同过滤推荐的音乐网站/基于vue的音乐平台
获取源码联系方式请查看文末🍅 摘 要 随着信息化时代的到来,系统管理都趋向于智能化、系统化,音乐推荐网站也不例外,但目前国内的有些公司仍然都使用人工管理,公司规模越来越大,同时信息量也越来越庞大&…...

STM32智能工业监控系统教程
目录 引言环境准备智能工业监控系统基础代码实现:实现智能工业监控系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景:工业监控与优化问题解决方案与优化收尾与总结 1. 引言 智能工业监控系统通…...
WEB渗透Web突破篇-SQL注入(MYSQL)
注释符 # -- 注意这里有个空格 /* hello */ /*! hello */ /*!32302 10*/ MYSQL version 3.23.02联合查询 得到列数 order by或group by 不断增加数字,直到得到报错响应 1 ORDER BY 1-- #True 1 ORDER BY 2-- #True 1 ORDER BY 3-- #True 1 ORDER BY 4-- #Fal…...

PDF解锁网站
https://smallpdf.com/cn/unlock-pdfhttps://smallpdf.com/cn/unlock-pdfhttps://www.freemypdf.comhttps://www.freemypdf.com...

【Redis】主从复制分析-基础
1 主从节点运行数据的存储 在主从复制中, 对于主节点, 从节点就是自身的一个客户端, 所以和普通的客户端一样, 会被组织为一个 client 的结构体。 typedef struct client {// 省略 } client;同时无论是从节点, 还是主节点, 在运行中的数据都存放在一个 redisServer 的结构体中…...

Transformer自然语言处理实战pdf阅读
一.第一章 欢迎来到transformer的世界 1.解码器-编码器框架 在Transformer出现之前,NLP的最新技术是LSTM等循环架构。这些架 构通过在神经网络连接使用反馈循环,允许信息从一步传播到另一 步,使其成为对文本等序列数据进行建模的理想选择。如…...

Python 高阶语法
前言: 我们通过上篇文章学习了Python的基础语法,接下来我们来学习Python的高阶语法 1.初识对象 在Python中我们可以做到和生活中那样,设计表格、生产表格、填写表格的组织形式的 面向对象包含 3 大主要特性: 封装 继承 …...

开始尝试从0写一个项目--前端(三)
器材管理板块 添加器材管理导航 src\views\home\Home.vue src\router\index.js src\views\equipment\Equipment.vue <template><div>hello!</div></template> 测试 搜索导航分页查询 src\views\equipment\Equipment.vue <template><div&…...
Visual stdio code 运行C项目环境搭建
参考 [1]VS Code 配置 C/C 编程运行环境(保姆级教程)_visual studio code c配置-CSDN博客 [2]最新VS code配置C/C环境(tasks.json, launch.json,c_cpp_properties.json)及运行多个文件、配置Cmake_vscode launch.json如何配置-CSDN博客 先装visual stdi…...

免杀笔记 -->API的整理Shellcode加密(过DeFender)
最近更新频率明显下降我懒,那么今天就来记录一下我们的一些常用的API的整理以及ShellCode的加密。 1.WinAPI整理 问我为什么要整理? 就是用起来的时候要左翻右翻 :: 烦死了 1.VirtualAlloc VirtualAlloc(NULL,sizeof(buf),MEM_…...

Stable Diffusion 使用详解(3)---- ControlNet
背景 炼丹师在AI绘画的过程中,由于Stable Diffusion的原理是水滴式的扩散作图原理,其实在前面也有提到,他的发挥是‘不稳定’的,因为你没有办法做到精确控制,只能说是大致符合你的预期。你不能总依赖抽卡固定随机数种…...

pythonGame-实现简单的贪食蛇游戏
通过python简单复现贪食蛇游戏。 使用到的库函数: import pygame import time import random 游戏源码: import pygame import time import randompygame.init()white (255, 255, 255) yellow (255, 255, 102) black (0, 0, 0) red (213, 50, 80…...

2024年软件系统与信息处理国际会议(ICSSIP 2024)即将召开!
2024年软件系统与信息处理国际会议(ICSSIP 2024)将于2024年10月25-27日在中国昆明举行。引领技术前沿,共谋创新未来。ICSSIP 2024将汇聚来自世界各地的专家学者,他们将在会上分享最新的研究成果、技术突破及实践经验。会议议题涵盖…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍
文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结: 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析: 实际业务去理解体会统一注…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...