在C#中通过使用方法来获取返回值时,通常只能得到一个返回值。因此,当一个方法需要返回多个值的时候,就需要用到ref和out,那么这两个方法区别在哪儿呢?

MSDN:
       ref 关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字。
      out 关键字会导致参数通过引用来传递。这与 ref 关键字类似,不同之处在于 ref 要求变量必须在传递之前进行初始化。若要使用 out 参数,方法定义和调用方法都必须显式使用 out 关键字。

案例:

定义一个方法,求一个整数数组中的最大值,最小值,和,平均数。如果是一个方法只能有一个返回值,那只能每一个都得定义一个方法来实现,不过有了ref和out这实现起来就方便多了。

ref:

    static int GetIntResult(int[] arry, ref float avg, ref int max, ref int min)
{
int sum = ;
max = arry[];
min = arry[];
for (int i = ; i < arry.Length; i++)
{
sum += arry[i]; if (max < arry[i])
{
max = arry[i];
}
if (min > arry[i])
{
min = arry[i];
}
}
avg = sum / arry.Length;
return sum;
}

然后在控制台中试着调用该方法:

      static void Main(string[] args)
{
int[] arr = { ,,,,,,,,};
float avg;
int max;
int min;
int sum = GetIntResult(arr, ref avg, ref max, ref min);
}

此时编译器就会提示画红线,错误:使用了未赋值的avg,max,min

       static void Main(string[] args)
{
int[] arr = { , , , , , , , , };
float avg = ;
int max = ;
int min = ;
int sum = GetIntResult(arr, ref avg, ref max, ref min);
Console.WriteLine("和:{0}\t平均值:{1}\t最大值:{2}\t最小值:{3}", sum, avg, max, min);
Console.Read();
}

运行结果:

总结:

ref这个关键字告诉c#编译器被传递的参数值指向与调用代码中变量相同的内存。这样,如果被调用的方法修改了这些值然后返回的话,调用代码的变量也就被修改了。

ref 关键字使参数按引用传递。其效果是,当控制权传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中(avg,max,min的初始值为0,调用方法后值改变)。若要使用 ref 参数,则方法定义和调用方法都必须显式使用 ref 关键字。

out:

换成out之后,上面的方法不再适用,报错,错误 : 控制离开当前方法之前必须对 out 参数“min”和"max"赋值。你会发现这里max和min在循环外并未初始化。所以才会出错。

修改后代码:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Wolfy.RefAndOut
{
class Program
{
static void Main(string[] args)
{
int[] arr = { , , , , , , , , };
float avg;//在使用out关键字时,不需要在此处初始化,初始化也不会影响到方法内部的值,所以你初始化没用
int max;
int min;
int sum = GetIntResult(arr, out avg, out max, out min);
Console.WriteLine("和:{0}\t平均值:{1}\t最大值:{2}\t最小值:{3}", sum, avg, max, min);
Console.Read();
}
static int GetIntResult(int[] arry, out float avg, out int max, out int min)
{
int sum = ;
max = arry[];
min = arry[];//使用out关键字时,必须在离开方法前对out关键字修饰的参数初始化
for (int i = ; i < arry.Length; i++)
{
sum += arry[i]; if (max < arry[i])
{
max = arry[i];
}
if (min > arry[i])
{
min = arry[i];
}
}
avg = sum / arry.Length;
return sum;
}
}
}

结果和上面一样。

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

结论:

关键字“ref“和”out”之间的唯一区别就是关键字”out“不要求调用代码初始化要传递的参数值。那么关键字‘ref”什么时候用呢?当您需要确保调用方法已经初始化参数值的时候,您就应该使用关键字“ref”。在上面例子中,能够使用“out“是因为被调用的方法并不依赖于被传递的变量的值。个中滋味慢慢体会......

后话:

在一论坛里面,偶然看到有这样的帖子,就顺便总结了一下,也算是回忆一下c#基础知识吧。

想深入了解的可以看这篇文章:http://www.cnblogs.com/dozer/archive/2011/10/28/ref-and-out-keywords.html

[C#基础]ref和out的区别的更多相关文章

  1. C#基础:ref和out的区别 [转]

    ref和out的区别在C# 中,既可以通过值也可以通过引用传递参数.通过引用传递参数允许函数成员更改参数的值,并保持该更改.若要通过引用传递参数, 可使用ref或out关键字.ref和out这两个关键 ...

  2. ref和out的区别?

    ref 和out的区别在面试中会常问到: 首先:两者都是按地址传递的,使用后都将改变原来参数的数值. 其次:ref可以把参数的数值传递进函数,但是out是要把参数清空,就是说你无法把一个数值从out传 ...

  3. 关于ref与out的区别

    写在最前面 这几天一直在公司接受培训,都是一些基础的知识,同时也乘着这个机会巩固一下自己的基础,基础太重要了.前些时一直看的是多线程方面的知识,接下来我会写一些其他方面的知识,毕竟作为一个实习新人得和 ...

  4. 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结

    史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...

  5. C#基础-ref、out

    1.默认情况下,C#假定所有的方法参数传递都是传值的. 如下面的方法: public static void Main(string[] args) { int val = 5; //调用AddVal ...

  6. ref和out的区别,值类型和引用类型的使用

    今天刚刚明白ref和out的区别,只限于个人理解如有不同请赐教,谢谢 首先我感觉ref和out是针对于值类型来说,以前一直认为是针对于引用类型看下面的一段代码 1.首先结果 i=0:ints[0]=0 ...

  7. ref和out的区别

    ref类型参数是按地址传递,能改变原来的数值.使用ref传参前,变量必须赋值. 带有ref类型参数的函数,不会清空变量,所以离开该函数的时候,所有ref引用的变量可以赋值也可以不赋值. out类型参数 ...

  8. 浅谈C#中ref与out的区别

    在C#这门高级语言中,你是否注意过ref与out的用法?你是否为在调用方法时需要多个返回值呢?不用急,接下来,我们去一起去研究一下这个问题... 其实呢,C#语言中,参数的传递一共有两种方法,值传递和 ...

  9. C#中的ref和out的区别

    转载原地址 http://www.cnblogs.com/gjahead/archive/2008/02/28/1084871.html ref和out的区别在C# 中,既可以通过值也可以通过引用传递 ...

随机推荐

  1. UWP 矢量字体图标(iconfont)使用

    本文使用 阿里巴巴开源字体: 选择矢量字体图标: 查看或编辑 Unicode编码 或字体名称 下载到本地,添加到uwp项目 代码中写法 Text:Unicode编码 FontFamily:文件路径#字 ...

  2. NYOJ--1237最大岛屿

    最大岛屿 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 神秘的海洋,惊险的探险之路,打捞海底宝藏,激烈的海战,海盗劫富等等.加勒比海盗,你知道吧?杰克船长驾驶着自己的的 ...

  3. [翻译]为你的服务器选择正确的.NET

    英文原文 By Daniel Roth ASP.NET 5 is based on the .NET Execution Environment (DNX), which supports runni ...

  4. jquery中的each()方法详解

    each()方法能使DOM循环结构简洁,不容易出错.each()函数封装了十分强大的遍历功能,使用也很方便,它可以遍历一维数组.多维数组.DOM, JSON 等等在javaScript开发过程中使用$ ...

  5. HDU 1828 / POJ 1177 Picture --线段树求矩形周长并

    题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 ...

  6. HDU 1556 Color the ball

    这题用线段树的话简直就是一个水题..不过刚学树状数组,要用一下. 题意:每次给你a,b,表明a~b之间涂色,然后最后一次输出每个气球被涂色的次数. 要用树状数组就要考虑怎么转化为前缀和问题,这题可以这 ...

  7. Eclipse去除JavaScript验证错误

    这篇文章主要是对Eclipse去除js(JavaScript)验证错误进行了介绍.在Eclipse中,js文件常常会报错.可以通过如下几个步骤解决 第一步: 去除eclipse的JS验证: 将wind ...

  8. java8-1 final

    1.final可以修饰类,方法,变量 特点: final可以修饰类,该类不能被继承. final可以修饰方法,该方法不能被重写.(覆盖,复写) final可以修饰变量,该变量不能被重新赋值.因为这个变 ...

  9. NSProgress

    苹果公司在 iOS 7 and OS X 10.9引入NSProgress类,目标是建立一个标准的机制用来报告长时间运行的任务的进度.NSProgress引入之后,其最重要的作用是可以在一个app的多 ...

  10. android实现点击背景图片不同区域实现不同事件

    有时候我们拿到一张背景图片,客户要求点击图片的不同区域去跳转或者实现不同的操作事件.我们首先要确认图片的点击区域,往往我们会在布局文件那里下手,但是这样不好做适配,所以我实现了以下方法,基本功能可以实 ...