以前一直误以为引用类型,在作为参数传递时,都是引用传递(类似于值传递中的ref),也就是说,把引用类型的变量作为参数传递给方法,在方法中修改该参数,会改变这个变量的值,

后来通过一些事例发现,上面的认识是片面的,引用类型传递实际上也是属于值传递的,只是引用类型传递的是一个堆地址。

先来个例子吧:

  1. using System;
  2. public class test{
  3. public static void Main(){
  4. testClass a = new testClass();
  5. ChangeToNull(a);
  6. Console.WriteLine(string.Format("a不是null,它的属性值为:{0}", a.field));
  7. ChangeField(a);
  8. Console.WriteLine(string.Format("a的属性值为:{0}", a.field));
  9. ChangeToNull(ref a);
  10. Console.WriteLine(string.Format("a是不是null:{0}", (a == null)));
  11. }
  12. static void ChangeToNull(testClass b){
  13. b = null;
  14. if(b == null){
  15. Console.WriteLine("在ChangeToNull方法中,参数已经被修改成null了!");
  16. }
  17. }
  18. static void ChangeField(testClass b){
  19. b.field = 0;
  20. Console.WriteLine("在ChangeField方法中,参数的成员已经被修改成0了!");
  21. }
  22. static void ChangeToNull(ref testClass b){
  23. b = null;
  24. if(b == null){
  25. Console.WriteLine("在ChangeToNull使用ref的重载方法中,参数已经被修改成null了!");
  26. }
  27. }
  28. }
  29. class testClass{
  30. public int field;
  31. public testClass(){
  32. field = 123;
  33. }
  34. }

上面的代码,执行后的结果是:

在ChangeToNull方法中,参数已经被修改成null了!
a不是null,它的属性值为:123
在ChangeField方法中,参数的成员已经被修改成0了!
a的属性值为:0
在ChangeToNull使用ref的重载方法中,参数已经被修改成null了!
a是不是null:True

由此可见,引用类型作为参数时:

1、在修改变量本身时,结果类似于值传递,即不会改变传递前的变量的值

2、在修改变量的属性或字段时,才是引用传递,会影响到传递前的变量的值

3、参数使用了ref后,才是真正的引用传递,不管修改变量本身还是修改变量的属性或字段,都会影响到传递前的变量的值

究其原因,我们知道,值类型和引用类型,在运行时,它们存放的位置是不同的,值类型是存储在进程的栈上的

而引用类型是存储在进程堆(Heap)上的,在进程的栈上存储了这个引用类型在堆上的地址

而在调用方法时,是把栈上的参数的值复制一份传递给方法,所以值类型作为参数传递时,不会改变原变量值很明显

引用类型传递时,也是一样,把栈上的这个堆地址复制一份传递给方法,

所以在方法里修改这个复制的地址的值,当然不会改变原变量的值,

但是修改这个复制的地址所指向的堆里的内容,那原变量指向的地址的内容当然也跟着改变了。

如果参数加了ref,那传递的就是栈的地址的,此时不管是值类型还是引用类型,都会改变原变量的内容

综上所述,我们可以知道,引用类型作为参数传递,不能单纯的说它就是引用传递,如果直接这么认为,在开发中难免会犯错误的,深入的理解一下值类型和引用类型的传递,还是很有必要的。

最新文章

  1. C# 中的as和is小结
  2. etc 安装及使用
  3. DotNet 资源大全中文版,内容包括:编译器、压缩、应用框架、应用模板、加密、数据库、反编译、IDE、日志、风格指南等
  4. LNMP安装了哪些软件?安装目录在哪?
  5. if [-f build/core/envsetup.mk -a -f Makefile ]; then
  6. "ping: unknown host www.baidu.com" 解决方法
  7. Java Web整合开发(附录1) - 安装配置环境
  8. Google Maps API Web Services
  9. 一个基于node 的小demo
  10. c++简单编写线性表(实验)
  11. 集成支付宝SDK流程
  12. DNSCrypt
  13. python 定义带默认参数的函数
  14. Linux 进程后台运行
  15. boot项目swagger接口调试工具默认访问路径
  16. Linux学习笔记之五————Linux常用命令之用户、权限管理
  17. windows系统中搭建Jenkins服务器
  18. nginx 代理ssh
  19. [leetcode]Rotate Image @ Python
  20. linux 下 php 安装 libevent

热门文章

  1. 使用HttpClient向服务器发送restful post请求
  2. dump 验证实例恢复的起点和终点
  3. java学习之线程
  4. bzoj3091
  5. BZOJ1831: [AHOI2008]逆序对
  6. 【C++ in Qt5】一个简单的通讯录程序,支持文件存取
  7. 【转】Android中设置TextView的颜色setTextColor--代码中设置字体颜色
  8. 字符串(AC自动机):HDU 5129 Yong Zheng's Death
  9. 在Code First中使用Migrations对实体类和数据库做出变更
  10. OracleParameter 的使用(参数名要以:开头,不允许包含@等特殊字符)[转]