看如下代码:
 
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. Linux - ubuntu 设置固定ip和设置dns

    ubuntu 设置固定ip和设置dns 1.ifconfig 查看网卡名称 root@jiqing-virtual-machine:~# ifconfig ens32 Link encap:以太网 硬 ...

  2. 寄存器(CPU原理)

    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gra ...

  3. 策略模式--List排序

    需求:根据姓名进行排序,升序或者降序,如果名字一样,就按照id升序排序,用策略模式 步骤一: 定义一个Person对象 public class Person { private Integer id ...

  4. POI--帮助文档

    1.创建工作簿 (WORKBOOK) HSSFWorkbook wb = new HSSFWorkbook(); FileOutputStream fileOut = new FileOutputSt ...

  5. redis发布与订阅

    发布与订阅 除了实现任务队列外, Redis还提供了一组命令可以让开发者实现"发布/订阅"(publish/subscribe)模式. "发布/订阅"模式同样可 ...

  6. linux命令读取文件中特定行

    1.如果你只想看文件的前5行,可以使用head命令, 如: head -5 /etc/passwd 2.如果你想查看文件的后10行,可以使用tail命令, 如: tail -10 /etc/passw ...

  7. 【转载】C#.NET WebApi返回各种类型(图片/json数据/字符串),.net图片转二进制流或byte

    C#.NET WebApi返回各种类型(图片/json数据/字符串),.net图片转二进制流或byte 转载:http://www.itdos.com/Mvc/20150302/0741255.htm ...

  8. Java基础系列--Executor框架(一)

    文章来源:http://www.cnblogs.com/V1haoge/p/8393618.html 一.Executor框架介绍 Executor框架是JDK1.5之后出现的,位于juc包中,是并发 ...

  9. elasticsearch-5.x JAVA API(001)

    Elasticsearch JAVA API 极其广泛,把所有的方法意义介绍出来显然不太现实.从1.x到2.x,在到5.x,最后到6.0,也不过短短两三年的时间,我挑选了5.4.0版本分三部分把平时常 ...

  10. [DeeplearningAI笔记]神经网络与深度学习4.深度神经网络

    觉得有用的话,欢迎一起讨论相互学习~Follow Me 4.2 深层神经网络中的前向传播 4.3 核对矩阵的维数 经验方法论 对于神经网络想增加得到没有bug的程序的概率的方法:需要仔细的思考矩阵的维 ...