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将汇聚来自世界各地的专家学者,他们将在会上分享最新的研究成果、技术突破及实践经验。会议议题涵盖…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
