老生常谈C#中的 ref 与 out

在C#中,定义函数时,函数的参数有两种形式,分别是引用参数和值参数。

如果使用“值参数”,也就是说,我们给函数参数所使用的变量赋一个值,例如:

//定义一个函数

Public static void ValueTest(string var)

{

       Var = Var + "在末尾加点东西";          //这个函数的作用就是在Var的末尾加上"在末尾加点东西"

       Console.WriteLine("经过函数修改后的值:{0}",Var);

}

//调用此函数时,给参数var赋值,让var等于ValueStr的值

Public static void Main(strin[] args)

{

  string ValueStr = "初始化一个字符串";

      Console.writeLine("原来的值:{0}",ValueStr);

      ValueTest(ValueStr);

  Console.WriteLine("让我们来看看到底有没有改变ValueStr 的值:{0}",ValueStr);

}

//显示结果是:

原来的值:初始化一个字符串;

经过函数修改后的值:初始化一个字符串在末尾加点东西;

让我们来看看到底有没有改变ValueStr 的值: 初始化一个字符串;

结果显示,ValueStr的值没有改变,所以说通过值参数不能改变原变量的值,但有时我们确实想在函数中改变变量的值,那么我们就需要引用传递参数。

即函数所处理的变量与函数所调用的变量是相同的,因此在函数中对这个变量进行修改,那么就等于真正的修改了此变量,为此,只需要使用ref来指定参数,我们来对上例进行一下修改,例如:

public static void ValueTest(ref string var)           //注意在形式参数里添加了ref关键字

{

       Var = Var + "在末尾加点东西";          //这个函数的作用就是在Var的末尾加上"在末尾加点东西"

       Console.WriteLine("经过函数修改后的值:{0}",Var);

}

//调用此函数时,给参数var赋值,让var等于ValueStr的值

Public static void Main(strin[] args)

{

  string ValueStr = "初始化一个字符串";

  Console.writeLine("原来的值:{0}",ValueStr);

  ValueTest( ref ValueStr);                          //注意在调用函数时,必须在实参中指定ref

  Console.WriteLine("让我们来看看到底有没有改变ValueStr 的值:{0}",ValueStr);

}

//显示结果是:

原来的值:初始化一个字符串;

经过函数修改后的值:初始化一个字符串在末尾加点东西;

让我们来看看到底有没有改变ValueStr 的值: 初始化一个字符串在末尾加点东西;

结果显示ValueStr值被改变。在使用ref的时候我们要注意,调用变量之前,一定要给这个变量初始化,例如:

string ValueStr;

ValueTest( ref ValueStr); //这样是非法的。

还有一点要注意的是:我们使用ref的目的是用来修改变量的值,如果我们不能在函数中修改用ref 引用的参数变量,那么程序也是非法的。

例如:

Const string ValueStr = "初始化一个字符串";

ValueTest( ref ValueStr); //这样是非法的。

下面来说一下out,out也称为输出参数,out与ref关键字的使用方式相同(在函数定义和调用函数时,都必须用作参数的修饰符)。实际上,它们两个的作用也完全一样,都能够修改调用中使用的变量的值。

但是out与ref 有一些区别:

  1. 使用ref时,被用作参数的变量必须提前初始化,而使用out,则不需要,只需要要声明就可以。
  2. 使用out时,被用作参数的变量,即使提前初始化,在函数内使用该变量时,也会被当作未赋值。也就是说把此变量的值自动丢失处理。

下面我们来看一个使用out的例子:返回数组中的最大值,获取数组中最大值的元素下标。

Static void MaxValue(int[] iVar, out int indexMax)

{

       Int MaxV = iVar[0];

       For(int i = 1; i < iVar.length; i++)

      {

              If(MaxV < iVar[i])

              {

                     MaxV = iVar[i];

                     indexMax =  i;

     }

  }

return MaxV;

}

//调用此函数

Int[] myArray = {1,3,4,2,6,7,9,8};

Int indexMax;

Console.WriteLine("数组中最大值是:{0}",MaxValue(myArray,out indexMax));  //调用函数时,必须要加上out关键字

Console.WriteLine("数组中最大值的坐标是:{0}",indexMax);

显示结果:

数组中最大值是:9;

数组中最大值的坐标是:6;

从这个实例我们可以看出使用out后, indexMax的值被改变了。

关于ref 与 out我的理解是:函数定义时,加上这个两个关键字的其中之一后,就告诉编译器,这个参数名(例如:(ref string var)中的var)与所调用的实际变量(例如: string ValueStr = "初始化一个字符串"中的ValueStr;)指向同一个内存区域,而这个内存区域存储的就是"初始化一个字符串"这个值,也可以理解为var 与 ValueStr的内存地址是相同的,所以修改var,就是修改var所指向的值,而var 与 ValueStr指向同一个内存区域,所以也就相同于修改了ValueStr。

不知道这样理解对不对,请大虾们多多指点。

posted @ 2011-04-15 11:28  百黎  阅读(523)  评论(3编辑  收藏  举报