关于ref与out的区别
写在最前面
这几天一直在公司接受培训,都是一些基础的知识,同时也乘着这个机会巩固一下自己的基础,基础太重要了。前些时一直看的是多线程方面的知识,接下来我会写一些其他方面的知识,毕竟作为一个实习新人得和自己从事的具体方向靠近,不过感觉前些时的多线程学的还不够,今后有空还会继续,暂时到此吧、、、
昨天培训的时候有一个问题是关于ref和out的区别,悲催的我不知道,只晓得它们可以做引用传递,具体区别都没一个概念额,貌似当年教我们C#初级的尹老师提到过一个数字交换实现可以用这个,不过当时也就仅此仅此,今天来学习下下
首先声明下哈,此文参考了网上部分文章内容,然后结合自己的了解和总结,有不对的尽管拍砖
关于ref
经常听到值类型和引用类型,其实本质就是一个存储值一个存储地址,看看下面一段代码:
public class Test
{
public int num;
public Test(int x)
{
this.num = x;
}
public void ChangeNum(Test x)
{
x = new Test();
}
}
class Program
{
static void Main(string[] args)
{
Test ts = new Test();
ts.ChangeNum(ts);
Console.WriteLine(ts.num);
Console.ReadKey();
}
}
对于以上代码,你认为会输出什么结果?10?100?正确结果是10,猜100的肯定有疑问了、、、
接下来我改两个位置,就不复制整个了,贴出改位置的两个位置,如下所示:
ts.ChangeNum(ref ts); //改上面第18行
public void ChangeNum(ref Test x) //改上面第8行
对于这次的结果又得探讨了,10?还是100?正确结果为100

以上截图,左边是原始代码变量ts和x的地址,右边是修改两个位置后的ts和x的地址,从上面我们可以清晰的看见左图ts地址(0x05f0eb2c)和x地址(0x05f0eacc)不同,右图中ts的地址(0x0568ee6c)和x的地址(0x0568ee6c)相同。就是由于原始代码中Main函数中的ts和Test中的x不是同一个变量,所以后面执行18行代码不会对num值产生任何影响,而后面的两行代码就不同,因为所指向的是同一个变量,所以结果自然得以修改变为100
关于out
还是来看一段代码,事实比较好说话,呵呵:
public class Test
{
public int num;
public Test(int x)
{
this.num = x;
}
public void ChangeNum(out Test x)
{
x = new Test();
}
}
class Program
{
static void Main(string[] args)
{
Test ts = new Test();
Test x;
ts.ChangeNum(out x);
Console.WriteLine(ts.num);
Console.WriteLine(x.num);
Console.ReadKey();
}
}
以上这段代码执行打印的两个结果也是不同的,分别打印10和100,原理和上面差不多一样,是不是感觉和上面讲的ref很有点象,没错,所以有了今天的标题“关于ref与out的区别”,接下来谈谈其区别吧!
关于out和ref的区别
作为都可以作为引用传递,区别在于值传递。ref传递前必须初始化,而out不必初始化,就算初始化,也会被无视之,out 作为输出参数,可以解决函数只有一个返回值的问题
static void Main(string[] args)
{
Program pg = new Program();
int x;
pg.Method_1(out x);
Console.WriteLine(x);
int y = ;
pg.Method_2(ref y);
Console.WriteLine(y);
Console.ReadKey();
} public void Method_1(out int x)
{
x = ; //这一句必须要,不然报错
Console.WriteLine("调用Medthod_1");
} public void Method_2(ref int x)
{
x++;
Console.WriteLine("调用Medthod_2");
}
运行结果:

怀旧一下当年尹老师讲的a=5和b=10,a与b数值交换,就是用的ref
public void yy(ref int x,ref int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
static void Main(string[] args)
{
Program pg = new Program();
int a = ;
int b = ;
Console.WriteLine("a:" + a + ",b:" + b);
pg.yy(ref a,ref b);
Console.WriteLine("a:"+a+",b:"+b);
Console.ReadKey();
}
然后以上代码改为用out实现:
public void yy(int a,int b,out int x,out int y)
{
x = b;
y = a;
}
static void Main(string[] args)
{
Program pg = new Program();
int a = ;
int b = ;
Console.WriteLine("a:" + a + ",b:" + b);
pg.yy(a,b,out a,out b);
Console.WriteLine("a:"+a+",b:"+b);
Console.ReadKey();
}
自我感觉吧,在很多地方ref和out可以互换,起到相同的作用,区别仅仅在于ref传进去的参数必须在调用前初始化,out不必初始化;ref传进去的参数在函数内部可以直接使用,而out不可以;ref传进去的参数在函数内部可以不被修改,但out必须在离开函数体前进行赋值。个人感觉ref可以更随意的使用,out总有那么点别扭,毕竟必须在内部给其赋值。
实习的第一个双休日
貌似此文扯了些不该扯得,但总的来说都是跟随笔主要内容有些相关啦,接下来由于培训内容的相关,得转移重心了,Linq和EF还得再回去看看,所以后期可能写点哪方面相关知识。晚睡的习惯还木有改过来,这是个问题得治啊,听了一晚上的歌,单曲循环"想把我唱给你听",好晚了,睡觉去也!!!
------如果你觉得此文对你有所帮助,别忘了点击下右下角的推荐咯,谢谢!------
关于ref与out的区别的更多相关文章
- ref和out的区别,值类型和引用类型的使用
今天刚刚明白ref和out的区别,只限于个人理解如有不同请赐教,谢谢 首先我感觉ref和out是针对于值类型来说,以前一直认为是针对于引用类型看下面的一段代码 1.首先结果 i=0:ints[0]=0 ...
- ref和out的区别?
ref 和out的区别在面试中会常问到: 首先:两者都是按地址传递的,使用后都将改变原来参数的数值. 其次:ref可以把参数的数值传递进函数,但是out是要把参数清空,就是说你无法把一个数值从out传 ...
- ref和out的区别
ref类型参数是按地址传递,能改变原来的数值.使用ref传参前,变量必须赋值. 带有ref类型参数的函数,不会清空变量,所以离开该函数的时候,所有ref引用的变量可以赋值也可以不赋值. out类型参数 ...
- 浅谈C#中ref与out的区别
在C#这门高级语言中,你是否注意过ref与out的用法?你是否为在调用方法时需要多个返回值呢?不用急,接下来,我们去一起去研究一下这个问题... 其实呢,C#语言中,参数的传递一共有两种方法,值传递和 ...
- C#中的ref和out的区别
转载原地址 http://www.cnblogs.com/gjahead/archive/2008/02/28/1084871.html ref和out的区别在C# 中,既可以通过值也可以通过引用传递 ...
- C#中ref和out的区别浅析
这篇文章主要介绍了C#中ref和out的区别浅析,当一个方法需要返回多个值的时候,就需要用到ref和out,那么这两个方法区别在哪儿呢,需要的朋友可以参考下 在C#中通过使用方法来获取返回值时,通 ...
- 参数修饰符ref,out ,params的区别
参数修饰符ref,out ,params的区别 C#中有三个关键字-ref,out ,params,可是这三个之间的区别你都明白了吗? 那么我们就来认识一下参数修饰符ref,out ,params吧, ...
- ref与out的区别、冒泡排序、普通排序,以及二分法查询
一.首先我们先讲一下ref与out的区别和使用方法: 1.ref与out的区别: out:需要在使用前声明变量,分配地址但不能赋值,但是需要在使用中的时候需要初始化(进入方法体中的时候需要先赋值在使用 ...
- Spring框架xml配置中属性ref与value的区别
1.spring批量扫描mybatis的mapper,使用value 2.spring管理mybatis的单个mapper,用的是ref 虽然引用的是同一个bean,但两个对象的属相类型明显不一样,一 ...
随机推荐
- ArcMap 10.2 crashes during Loading Document launch stage
问题描述: ArcMap unexpectedly exits during the "Loading Document..." stage on startup. No erro ...
- iOS开发--UIKit控件之UISearchBar(搜索栏)
今天因为需求原因,需要用到搜索控件:之前一直没有用到过这个控件,所以去百度了一下,找到一篇可以说很齐全的资料,感谢这位作者. 然而,我并没有找到可以更改字体大小的属性或方法,希望有知道的告诉我一声,谢 ...
- ASP.NET MVC 之控制器与视图之间的数据传递
今天,我们来谈谈控制器与视图之间的数据传递. 数据传递,指的是视图与控制器之间的交互,包括两个方向上的数据交互,一个是把控制器的数据传到视图中,在视图中如何显示数据,一个是把视图数据传递到控制器中, ...
- JavaScript之数组对象
Array类型是ECMAScript中最常用的类型了. 一.声明方式 1.使用Array构造函数 var arr1 = new Array(); 如果预先知道要保存数组的数量, 也可以给构造函数传递该 ...
- Mysql 的安装与配置
MySQL的安装 第1步:下载 第2 步:以管理员身份进行安装 第3步:选择安装类型. 第4步:设置MySQL安装目录,及数据库文件目录 第5步:安装结束,开启配置向导 第6步:选择配置类型 第7步: ...
- Spring零碎知识复习
自学了Spring也有一段时间了,多多少少掌握了一些Spring的知识,现在手上也没有很多的项目练手,就将就着把这些学到的东西先收集起来,方便日后用到的时候没地方找. 1.spring的国际化 主要是 ...
- 如何在Android SDK 下查看应用程序输出日志的方法
该文章源于安卓教程网(http://android.662p.com),转载时要注明文章的来自和地址,感谢你的支持. 在Android程序中可以使用 android.util.Log 类来 ...
- javascript显示倒计时控制按钮
html: <a><span id="sendAgain" onclick="sendEmail()">2.再次发送激活邮件</s ...
- Wpf 简单制作自己的窗体样式(2)
上一篇blog讲了制作简单的样式的窗体,对于一个传统的窗体,不仅仅可以拖动,和关闭操作.还具有最大化.最小化.隐藏,以及改变窗体的大小等.这篇blog就是对上篇的补充,完善窗体的改变大小和最大化最小化 ...
- cadence 焊盘制作小结
因为以前一直用altium designer 话PCB,做封装的时候焊盘是不用自己操心的,但是开始用cadence以后发现好多以前不太懂的东西,需要自己画焊盘,这就导致需要了解好多自己以前不懂的东西, ...