A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 yy312232557 于 2011-11-6 17:18 编辑

------------- Windows phone 手机开发 、ASP .NET培训、期待与您交流!----------------


说真的,这个ref和out的一直没怎么搞清楚,为什么呢?

  因为好像在实际开发过程当中,真的没怎么用到过,网上看别人的教程,也没见到特别多的关于他们的用法

今天又重新看了杨老师的视频,将这个再次好好理解了一边,现在将这些写下来

总的来说,通常我们向方法中传递的是值.方法获得的是这些值的一个拷贝,然后使用这些拷贝,当方法运行完毕后,这些拷贝将被丢弃,而原来的值不将受到影响.此外我们还有其他向方法传递参数的形式,引用(ref)和输出(out).

引用是一个变量,他可以访问原来变量的值,修改引用将修改原来变量的值.变量的值存储在内存中,可以创建一个引用,他指向变量在内存中的位置.当引用被修改时,修改的是内存中的值,因此变量的值可以将被修改.当我们调用一个含有引用参数的方法时,方法中的参数将指向被传递给方法的相应变量


不知道这样说对不对?凭着感觉理解的

若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字。
out 关键字会导致参数通过引用来传递。这与 ref 关键字类似,不同之处在于 ref 要求变量必须在传递之前进行初始化。


若要使用 out 参数,方法定义和调用方法都必须显式使用 out 关键字。

下面写个简单例子
  1. static void TestRefAndOut()
  2. {
  3. string s1 = "Good Luck!";
  4. TestRef(ref s1);
  5. Console.WriteLine(s1);//output: Hello World!
  6. }
  7. static void TestRef(ref string str)
  8. {
  9. str = "Hello World!";
  10. }
复制代码
在TestRefAndOut()中将字符串s1以ref关键字的方式传到方法TestRef(ref string str)中,在这个方法中,

我们改变了s1的引用变量str的值,最后,回到TestRefAndOut()方法后输出s1的值,发现其值已被改变。
如果将上例中的ref换成out,代码如下:
  1. static void TestRefAndOut()
  2. {
  3. string s1 = "Good Luck!";
  4. //TestRef(ref s1);
  5. TestOut(out s1);
  6. Console.WriteLine(s1);//output: Hello World!
  7. }

  8. static void TestOut(out string str)
  9. {
  10. str = "Hello World!";
  11. }
复制代码
同样,在将ref换成out后,会发现最后的输出仍然是相同的,那这两个关键字的区别是什么呢?
进一步测试:
ref:
  1. static void TestRefAndOut()
  2. {
  3. string s1 = "Good Luck!";
  4. TestRef(ref s1);
  5. }

  6. static void TestRef(ref string str)
  7. {
  8. Console.WriteLine(str);//output: Good Lick!
  9. }
复制代码
out:
  1. static void TestRefAndOut()
  2. {
  3. string s1 = "Good Luck!";
  4. TestOut(out s1);
  5. }

  6. static void TestOut(out string str)
  7. {
  8. Console.WriteLine(str);//compile does not pass
  9. }
复制代码
ref的那段代码顺利编译,输出"Good Luck!",而out那段代码却无法通过编译,提示“Use of unassigned out parameter 'str' ”,
即使用了未分配地址的out参数str。怎么回事呢?

原来out参数在进入方法的时候,C#会自动清空它的一切引用和指向,所以在上面的out例子中,必需先要为str参数赋值。如以下程序。
  1. static void TestRefAndOut()
  2. {
  3. string s1 = "Good Luck!";
  4. TestOut(out s1);
  5. }
  6. static void TestOut(out string str)
  7. {
  8. str = "Hello World!";
  9. Console.WriteLine(str);//output: Hello World!
  10. }
复制代码
Ok,得到第一个区别: out 参数在进入方法(函数)时后清空自己,使自己变成一个干净的参数,也因为这个原因必须在方法返回之前或再使用out参数前为 out 参数赋值(只有地址没有值的参数是不能被.net接受的);
而ref参数是不需要在被调用方法使用前先赋值的,甚至也可以被调用方法中不改变ref参数的值,这都不会引起编译错误。
在继续看一段代码:
ref:
  1. static void TestRefAndOut()
  2. {
  3. string s1;
  4. TestRef(ref s1);
  5. Console.WriteLine(s1);//compile does not pass!
  6. }
  7. static void TestRef(ref string str)
  8. {
  9. str = Hello World!";
  10. }
复制代码
out:
  1. static void TestRefAndOut()
  2. {
  3. string s1;
  4. TestOut(out s1);
  5. Console.WriteLine(s1);//output: Hello World!
  6. }

  7. static void TestOut(out string str)
  8. {
  9. str = "Hello World!";
  10. }
复制代码
这回发现,ref这段代码无法编译了,s1是一个空引用,所以无法使用。而out参数则因为上述的那个原因,它不在乎s1是不是空引用,因为就算s1不是空引用,它也会把s1变成空引用的。Ok,第二个区别:ref参数在使用前必需初始化,而out不需要。嗯,由上边两个区别可以引申一下,out参数只进不出,ref参数有进有出。在用法上概括一下就是:out适合用在需要retrun多个返回值的地方,而ref则用在需要被调用的方法修改调用者的引用的时候。

基本上就测试到这里了,基本上是理解了,可是不知道在项目中怎么用。



------------- Windows phone 手机开发 、ASP .NET培训、期待与您交流!----------------

评分

参与人数 1技术分 +2 收起 理由
杨恩锋 + 2

查看全部评分

9 个回复

正序浏览
呵呵  看看
回复 使用道具 举报
anyu 中级黑马 2012-11-11 13:11:04
9#
楼主写的很详细,多谢楼主了,学习了···
回复 使用道具 举报
anyu 中级黑马 2012-11-11 13:10:22
8#
楼主最后一句写错了吧?out应该是只出不进吧?
回复 使用道具 举报
李荣壮 黑马帝 2011-11-6 21:52:46
7#
额...不是说用真实姓名的, 现在也可以用昵称了?
回复 使用道具 举报
好音啊。。
学习了
回复 使用道具 举报
10642491 发表于 2011-11-6 17:42
楼主真是好人啊,向你学习。

过奖了过奖了!
只能说是相互学习, 要记住一点:学习是要和大家一起分享的,在分享的同时,也是对自己知识的巩固

很多问题,自己可能一知半解,但是在给别人讲的时候,你就会心里努力的去想,我要怎么跟你讲,你才能明白呢?那么在这个过程中,你自己会学到的更多

呵呵,姚某人在这里班门弄斧了,见笑
回复 使用道具 举报
yy312232557 发表于 2011-11-6 17:14
我是单独写在CSDN里面的,写好了copy一份过来到这边,供大家一起学习看看,交流一下啊 ...

楼主真是好人啊,向你学习。
回复 使用道具 举报
黄威 发表于 2011-11-6 17:01
怎么把黑马日记写到论坛里面啦?

我是单独写在CSDN里面的,写好了copy一份过来到这边,供大家一起学习看看,交流一下啊
回复 使用道具 举报
怎么把黑马日记写到论坛里面啦?
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马