浅谈C#中对引用类型的误解

作者:qylost 时间:2021-10-18 12:40:37 

值类型和引用类型作为两个非常基础而且很重要的概念,一般我们都是在最开始的时候学的,你听到的可能是这样的:值类型传递的是具体的值(副本),引用类型传递的是引用,对于前者大家都不会有什么疑惑,但是在引用类型上就可能会进入一些误区。

概念插入:

值类型:值类型传递的是数据的副本,也就是将整个数据进行Copy然后赋值给另一个变量。

引用类型:传递的是对象的地址/路径(一般都会叫做引用),在对象的赋值过程中实际上是把目标对象的地址以副本的形式给了接收的对象。

实例说明

如下我们新建了一个Student类,定义了一个变量student1,然后定义了一个变量student2并将student1赋值给了它,紧接着创建了student3并将student3赋值给了student1。

输出结果:1


class Program
{
 static void Main(string[] args)
 {
   //step1
   Student student1 = new Student() { StudentId = 1 };
   Student student2 = student1;
   Student student3 = new Student() { StudentId = 3 };
   //step2
   student1 = student3;
   Console.WriteLine(student2.StudentId.ToString());
   Console.ReadKey();
 }
}
public class Student
{
 public int StudentId { get; set; }
}

Step1的操作如下图所示:

浅谈C#中对引用类型的误解

在图中的右侧我们使用矩形代替两个通过new关键字创建的对象,并为其标识了两个虚拟的ID,在左侧我们定义了三个变量,如图的圆角矩形所示,这三个变量不是真正意义上的对象,只是对象的一个所在地址而已,也就是我们通过这个变量就可以找到一个特定的地址。其中student1变量持有的ID(内存地址)为1001,student2也是1001,student3为1002。这里需要注意的是student1的1001和student2的1001虽然都是指向的1001,但是这两个1001都只是对象地址的一个副本,也就是说student1的1001和student2的1001并不是同一个,只是被Copy了而已(可以理解为这个地址是以值类型的方式进行传递的)。

这里要注意的是变量student2和student1是没有关系的,它们只和右侧的1001有关系,只是它们地址的值是相等的。

new关键字:

创建特定对象的实例并返回其引用地址(只是返回了地址的一个副本,而不是真正的对象)

When the object is created, the memory is allocated on the managed heap, and the variable holds only a reference to the location of the object.(来源于官方文档:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/types/)

译:创建对象后,内存会在托管堆上进行分配,并且变量只保留对对象位置的引用。

Step2的操作如下图所示:

在Step2的代码中我们将student3的变量赋值给了student1,那么这段代码执行的是将student3对应的ID(引用地址)以副本的方式给了student1。


//step2
student1 = student3;
Console.WriteLine(student2.StudentId.ToString());
Console.ReadKey();

浅谈C#中对引用类型的误解

如果你对引用传递理解有有偏差的话你可能会认为student2的地址也会变成1002,也就是student2.StudentId变成了3。这样理解是不正确的,我们刚才说过了虽然它们的引用地址是都是1001,但是这个地址也是通过副本进行传递的。也就是说当student1的地址发生改变并不会影响student2的地址。

浅谈C#中对引用类型的误解

再述:

当右侧对象中的值发生改变时,通过左侧变量来获取拿到的就是改变后的值,而当左侧变量值的改变时并不会影响右侧对象值的。左侧变量值的改变只是对应的地址发生了改变而不是对象的值发生了改变。

浅谈C#中对引用类型的误解

举例分析

这里从我们常用的两个购物平台淘宝、京东来举例说明引用地址传递。

右侧有两个对象分别是淘宝和京东,左侧我们定义了三个变量来保存这个对象的地址(和上边的例子是一样的)

浅谈C#中对引用类型的误解

如下图,我们将valA变量存放的地址改成了www.jd.com ,我们只是改变了变量存放的地址而并没有改变valA之前所对应的对象的值。

浅谈C#中对引用类型的误解

总结

引用类型传递的是对象的引用,是将引用地址以副本的方式进行传递。

来源:https://segmentfault.com/a/1190000019968579

标签:C#,引用类型
0
投稿

猜你喜欢

  • Java中instanceof关键字实例讲解

    2023-08-04 07:48:31
  • JAVA实现社会统一信用代码校验的方法

    2023-04-10 08:38:21
  • MyBatis-Plus多表联查(动态查询)的项目实践

    2023-11-19 21:43:17
  • java实现的RSA加密算法详解

    2022-11-19 06:14:44
  • IDEA中的.iml文件和.idea文件夹

    2023-11-23 11:47:19
  • 第一次使用Android Studio时你应该知道的一切配置(推荐)

    2022-01-08 00:49:38
  • 基于Java8 Stream API实现数据抽取收集

    2021-10-01 03:13:03
  • Maven配置多仓库无效的解决

    2023-11-29 04:37:10
  • 详解安装Eclipse Maven插件的几种方法

    2022-06-01 06:15:20
  • Java使用Maven BOM统一管理版本号的实现

    2023-08-30 00:46:00
  • java实现简单斗地主(看牌排序)

    2023-09-12 14:42:40
  • Windows编写jar启动脚本和关闭脚本的操作方法

    2021-05-28 04:36:58
  • 在IDEA里gradle配置和使用的方法步骤

    2023-11-23 16:07:58
  • SpringBoot 整合mybatis+mybatis-plus的详细步骤

    2022-09-29 21:06:10
  • Spring Boot调用 Shell 脚本实现看门狗功能

    2023-09-14 18:52:07
  • Spring Cloud中Sentinel的两种限流模式介绍

    2021-11-22 00:38:10
  • Spring Boot Thymeleaf实现国际化的方法详解

    2023-11-24 06:01:01
  • Mybatis在sqlite中无法读写byte[]类问题的解决办法

    2021-08-06 21:06:07
  • Java编程中实现归并排序算法的实例教程

    2023-09-10 07:40:41
  • FasfDFS整合Java实现文件上传下载功能实例详解

    2022-05-27 02:30:46
  • asp之家 软件编程 m.aspxhome.com