看如下代码:
 
void Test(T t);
void Test(ref T t);
当T是值类型的时候,很好判断,第一种并不能改变方法外变量的值,需要第二种方法才可以。通过查看IL代码,可以看到第二种方法是直接传的原变量T的地址,这里并没有发生装箱行为(如果发生装箱的话,会在堆中新建一个T变量,这也不会改变原来T变量的值,因此不成立)。
当T是引用类型的时候,第一种其实也相当于值传递,不过是原变量的地址给了t这个变量,最终操作的是同一个对象。而用ref的话,就没有地址复制这一步,直接把原变量的地址传了进去,当然结果都是一样的。
 
*但如下情况需要注意的是
 
        static void Main(string[] args)
{
UserInfo info = new UserInfo();
Console.WriteLine("调用方法之前哈希code:{0}", info.GetHashCode());
Reset(info);
Console.WriteLine("调用方法之后哈希code:{0}", info.GetHashCode());
Console.ReadKey();
} public static void Reset(UserInfo info)
{
Console.WriteLine("Reset赋值之前的哈希code:{0}", info.GetHashCode());
UserInfo user = new UserInfo();
info = user;
Console.WriteLine("Reset赋值之后哈希code为{0}", info.GetHashCode());
}
查看输出:
 
可以看到,如果不使用ref,传入的是引用的一个副本,这个副本存储的地址和传入的变量是一致的,引用同一个对象,因此哈希值相同。
给这个副本赋新的变量地址后,哈希值发生了改变。
但这总归是发生在复制的副本身上,原来的变量,哈希值未改变。
值得注意的是,如果info里面的参数,在Reset中info = user这个语句之后,发生了任何改变,都已经不会体现到Reset外围。
比如info.userName = "aa";
在info = user语句之后,加入 info.userName = "cc"。
在最后Console.ReadKey之前输出userName, 它还是"aa"。
Reset里面的info已经完全指向另外一个对象了。
 
如果我们在Reset方法的参数之前加上ref
 
那就是直接使用外围变量的值了,任何操作都直接影响外围传入的变量。包括上述说的userName也会被改变。整个来说就是原来变量地址上的类被换了一个。
 
综合来说,如果只是改变原有变量的内部变量值之类的操作,加不加ref都一样,当涉及到new赋值操作的时候,除非是刻意需要这么做,不然推荐加ref。

C#中引用变量是否应该加ref?的更多相关文章

  1. sed中引用变量

    sed 中引用变量 eval sed 's/string/$REPLACE/g' file awk 中引用变量 awk 在匹配字符串的时候,有时候需要需要引用变量. $pid= eval " ...

  2. awk中引用变量使用单引号''

    举例如下 who命令输出第一列 (1)第一种情况不使用引号 # i=1;who | awk '{print $${i}}' 输出如下: awk: {print $${i}} awk:          ...

  3. linux中环境变量和系统加载环境变量的顺序

    一.系统环境变量: /etc/profile :这个文件预设了几个重要的变量,例如PATH, USER, LOGNAME, MAIL, INPUTRC, HOSTNAME, HISTSIZE, uma ...

  4. 引用变量类型的加载顺序(类名+引用名=new +类名();)

    程序如下: 运行结果如下: 以上结果说明:同一个引用名称(可以把它当做变量的一种类型)可能指代不同的对象,依据同一个引用是否处于同一个初始化的层次,决定是否在完成: static Cup c1=new ...

  5. 为什么在匿名内部类中引用外部对象要加final修饰符

    当所在的方法的形参需要被内部类里面使用时,该形参必须为final. 为什么必须要为final呢? 首先我们知道在内部类编译成功后,它会产生一个class文件,该class文件与外部类并不是同一clas ...

  6. python,在路径中引用变量的方法

    fr = open('E:\\pyCharm\\LogisticRegression\\1\\'+变量+'.txt')

  7. with open()函数中,如何在文件名设置中引用变量(python)

    name = "wangyang" age = " with open("C:/Users/mike1/Desktop/name_age.txt", ...

  8. C++引用变量(转)

    引用变量 c++中引用变量的使用: 定义: int rate=80; int  & pt=rate 1.pt 是引用变量,申明引用变量时必须将其初始化.pt 和rate 的值指向相同的内存变量 ...

  9. PHP关于foreach使用引用变量的坑

    写PHP好多年,但仍然会犯低级错误,今天遇到个 foreach中引用变量时的坑,PHP版本为 5.6.12 代码如下: <?php $arr = ['a', 'b', 'c', 'd', 'e' ...

随机推荐

  1. servlet多线程问题

    Servlet本身是单实例的,这样当多个用户同时访问某个Servlet时,会访问该唯一的Servlet实例中的成员变量,如果对成员变量进行写入工作,那就会导致Servlet的多线程问题,即数据不一致. ...

  2. [知了堂学习笔记]_eclipse引入svn插件,并将项目同步到svn

    1. eclipse中不存在SVN问题的解决 1.1发现Team->Share project 下没有svn. 1.2下载安装svn插件. 选择help->Eclipse Marketpl ...

  3. linux nvme的sendfile流程

    在nvme的硬盘上使用sendfile系统调用,到底需要经过哪些流程? do_sendfile--->do_splice_direct-->splice_direct_to_actor-- ...

  4. requests关于Exceeded 30 redirects问题得出的结论

    昨天一个朋友在爬网页时出现的一个问题,以及后续我对这个问题进行了简单的测试. 先说出现的问题的简单描述. 首先是使用urllib请求网页: #urllib.request发起的请求 import ur ...

  5. Android studio修改包名

    最后一步,需要手动修改工程 build.gradle文件中的applicationId改为跟你的包名一致即可,

  6. win10预览版无开始菜单解决方案

    1.按下Win+R键打开“运行”程序,键入gpedit.msc 回车以打开本地组策略编辑器 2.调到图示位置将windows设置->安全设置->本地策略->安全选项->“用户账 ...

  7. MySQL备份利器-xtrabackup的介绍和原理(附脑图)

    标签(linux): mysql-xtrabackup 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 xtrabackup是Percona公司针对mysql数据 ...

  8. JSP与HTML及前后分离

    JSP是什么 首先要知道JSP的本质其实是个Servlet,index.jsp在访问的时候首先会自动将该页面翻译生一个index_jsp.java文件,即Servlet代码. 打开这个类你会发现这个类 ...

  9. oracle pl/sql如何定义变量

    目的:如何在pl/sql中定义基本类型,引用类型,记录型变量? 以下plsql程序用的scott用户的dept,emp表. 定义基本类型的变量 set serveroutput on ; --使用基本 ...

  10. jquery实现上传图片本地预览效果

    html: <img id="pic" src="" ><input id="upload" name="fil ...