浅谈C#中的值类型和引用类型

作者:Joye.Net 时间:2023-10-30 21:41:41 

一、基本概念

C#只有两种数据类型:值类型和引用类型

值类型在线程栈分配空间,引用类型在托管堆分配空间

值类型转为引用类型称成为装箱,引用类型转为值类型称为拆箱

以下是值类型和引用类型对照表

浅谈C#中的值类型和引用类型

从上图可以简单看出:string,Object,数组,class是引用类型,简单类型,枚举,结构是值类型。

二、代码展示

定义一个类和结构调用赋值

浅谈C#中的值类型和引用类型

内存分配情况如下图:

浅谈C#中的值类型和引用类型

从这张图可以看出,class实例化出来的对象,指向了内存堆中分配的空间;truct实例化出来的对象,是在内存栈中分配。

修改代码如下:

浅谈C#中的值类型和引用类型

内存分配情况:

浅谈C#中的值类型和引用类型

由上图可以知:


object obj=”abc”;
string i=(string)obj;

值类型和引用类型储的位置不一样
如果是引用类型,当两个对象指向同一个地方,修改某一个的时候,其它对象的值会发生改变

using System;namespace ConsoleApplication2{  //引用类型(因为‘class')  public class SomeRef  {    public int x { get; set; }  }  //值类型(因为‘struct')  public struct SomeVal  {    public int x{ get; set; }  }  class Program  {    static void Main(string[] args)    {      SomeRef r1=new SomeRef(); //在堆上分配      SomeVal v1 = new SomeVal();//在栈上分配      r1.x = 5;    //提领指针      v1.x = 5;    //在栈上修改      Console.WriteLine(r1.x); //显示5       Console.WriteLine(v1.x); //显示5      SomeRef r2 =r1; //只复制引用(指针)      SomeVal v2 =v1; //在栈上分配并赋值成员      r1.x = 8;    //r1.x和r2.x都会修改      v1.x = 8;    //v1.x会更改,v2.x不会      Console.WriteLine(r1.x); //显示8       Console.WriteLine(r2.x); //显示8       Console.WriteLine(v1.x); //显示8      Console.WriteLine(v2.x); //显示5      Console.ReadKey();    }  }}

三、值类型装箱、拆箱

1、装箱:就是将值类型的数据打包到引用类型的实例中(比如将string类型的值abc赋给object对象obj)

String i=”abc”;
object obj=(object)i;

装箱时到底发生的事情:

1)、在托管堆中分配内存。分配的内存量是值类型各字段所需的内存量,还要加上托管堆所有对象都有的两个额外成员(类型对象指针和同步块索引)所需的内存量

2)、值类型的字段复制到新分配的堆内存

3)、返回对象地址,现在该地址是对象引用;值类型成了引用类型

2、拆箱:就是从引用数据中提取值类型(比如将object对象obj的值赋给string类型的变量i)

object obj=”abc”;
string i=(string)obj;

拆箱不是装箱过程倒过来,拆箱的代价爱比装箱低的多,拆箱是获取指针的过程,该指针指向包含在一个对象中的原始值类型。

拆箱后将堆中的字段包含的值复制栈的值类型实例中。

3、值类型变为引用类型不一定要装箱,例如:

string str = "joye.net" + 26; //需要将26装箱为string类型
string str1 = "joye.net" + 26.ToString(); //tostring后不需要装箱

感兴趣的可以用IL看一下。

标签:值类型,引用类型
0
投稿

猜你喜欢

  • 浅谈Java关闭线程池shutdown和shutdownNow的区别

    2021-12-28 04:43:44
  • Java实现文本编译器

    2022-10-21 18:33:20
  • C# 爬虫简单教程

    2022-04-24 14:10:53
  • java实现表单必填参数验证的方法

    2023-06-16 21:41:24
  • Android studio 混淆配置详解

    2023-02-16 19:17:22
  • Java多线程状态及方法实例解析

    2021-09-10 22:49:53
  • C#实现文件上传以及多文件上传功能

    2023-06-19 15:36:17
  • ProtoStuff不支持BigDecimal序列化及反序列化详解

    2022-09-19 06:53:30
  • Android Handle原理(Looper,Handler和Message)三者关系案例详解

    2023-08-25 22:51:47
  • java多线程创建及线程安全详解

    2022-12-02 18:58:51
  • 深入了解Java接口回调机制

    2023-11-09 15:52:05
  • 解决springcloud中Feign导入依赖为unknow的情况

    2022-02-03 14:05:45
  • Spring boot中filter类不能注入@Autowired变量问题

    2023-04-24 14:17:41
  • Java基础知识之Java语言概述

    2023-11-28 04:36:35
  • C语言实现通讯管理系统设计

    2022-12-29 13:04:50
  • Android10.0实现本地音乐播放(附源码下载)

    2022-12-05 20:29:40
  • 详解Spring 中 Bean 的生命周期

    2023-09-13 14:55:57
  • 使用PackageManager获得应用信息实例方法

    2023-09-10 22:59:30
  • java算法实现预测双色球中奖号码

    2022-06-19 17:01:22
  • 图文详解OkHttp的超时时间

    2022-05-14 13:50:23
  • asp之家 软件编程 m.aspxhome.com