看如下代码:
 
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. CCF系列之数位之和(201512-1)

    试题编号: 201512-1试题名称: 数位之和时间限制: 1.0s内存限制: 256.0MB问题描述: 问题描述 给定一个十进制整数n,输出n的各位数字之和. 输入格式 输入一个整数n. 输出格式 ...

  2. eclipse怎么修改工作空间路径

    1.打开eclipse,在eclipse界面中的菜单栏中点击“文件”,如果您的eclipse是英文版,那么应该是file,打开后点击“切换工作空间" 2.如果您的eclipsehi英文版,则 ...

  3. 我的Android手册

    目录解释说明 assets文件说明 app_id:机智云 app id app_secret:机智云 app secret product_key:机智云 product key wifi_type_ ...

  4. 关于 tomcat 配置时遇到的问题与警告及解决办法

    首先,我们在日常配置 tomcat 时,总是会遇到这样的问题: 有时候我们会重新头来配置 tomcat,但是现在我们并不需要那么做,方法很简单,请继续往下看: 这个问题是告诉我们 tomcat 在 4 ...

  5. EL表达式和JSTL核心标签库

    1 EL表达式 1.1 EL的概述 EL,全名为Expression Language. 主要作用: ①EL表达式主要用于替换jsp页面中的脚本表达式,以便于从各种类型的web域中检索java对象(某 ...

  6. AM调制的FPGA实现

    一.说明: 功能:AM调制 平台:Vivado 2016.4 和 Matlab R2017a 二.原理: 1. AM调制原理 AM已调信号的时域表达式: 已调信号的频域表达式: 本质上AM调制就是频谱 ...

  7. SpringMVC 参数绑定注解解析

    本文介绍了用于参数绑定的相关注解. 绑定:将请求中的字段按照名字匹配的原则填入模型对象. SpringMVC就跟Struts2一样,通过拦截器进行参数匹配. 代码在 https://github.co ...

  8. JAVA泛型使用方法总结

    1. 基本概念: (1)什么是泛型? 泛型,即"参数化类型".即将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用或 ...

  9. HTML基础知识概括

    1.html的概念 HTML是用来描述网页的一种语言. HTML指的是超文本标记语言(HyperText Markup Language) HTML不是一种编程语言,而是一种标记语言(markup l ...

  10. 话说CentOS6的启动流程

    1.按下开机按钮,电脑的主板通电,电脑开始加电自检(POST,Power On and Self Test),测试主机的硬件是否满足开机的要求. 2.加载主板上的BIOS(Base Input/Out ...