C#中ref out
因为C#中参数默认是引用的,所以一直没注意ref及out参数修饰符的作用。一般的参考资料也没说清楚这二者的作用。
其实可以这样理解:ref及out就相当于C/C++中的对参数取指针,使用时就相当于把该参数的实际地址传到函数中,可以在函数中对其进行赋值。而指针与引用的差别在这里也是可以体现出来的:class TestApp
{
public
static void foo1(StringBuilder
s)
{
s.Append(" World");
s = new StringBuilder("foo1");
}
public
static void foo2(ref StringBuilder s)
{
s.Append(" World");
s = new StringBuilder("foo2");
}
public
static void
{
StringBuilder
s = new StringBuilder("Hello");
foo1(s);
Console.WriteLine(s.ToString());
foo2(ref s);
Console.WriteLine(s.ToString());
Console.ReadLine();
}
}
}
这里的两次输出将分别是“Hello World”和“foo2”。通过这个例子应该可以较明显地区分加和不加ref的区别了。
而ref与out的区别就在于out类型的参数可以不必初始化,就是说可以未初始化的变量到函数体内,而必须在函数体内对该参数变量赋值。使用了ref或out后,在调用函数时参数必须显式地写明ref或out,且必须是lvalue。两个区别是:第一个函数的new出来的是在一个新地址上。。原先stringbuilder的改变只是加个"Hello,World"..
第二个保证了地址不变的地方new。因此替换了原先位置的值为foo2
---------------------------------------------------------------------------------------------------------
ref是传递参数的地址,out是返回值,两者有一定的相同之处,但是也有不同点。
使用ref前必须对变量赋值,out不用。
out的函数会清空变量,即使变量已赋值也不行,退出函数时任何out引用的变量都要赋值,ref引用的能够修改,也能够不修改。
区别能够参看下面的代码:
using System;
using System.Collections.Generic;
using System.Text;
namespace @ref
{
class
TestApp
{
static
void outTest(out
int x, out int y)
{//离开这个函数前,必须对x和y赋值,否则会报错。
//y
= x;
//上面这行会报错,因为使用了out后,x和y都清空了,需要重新赋值,即使调用函数前赋过值也不行
x = 1;
y = 2;
}
static
void refTest(ref
int x, ref int y)
{
x = 1;
y = x;
}
public
static void
{
//out
test
int a,
b;
//out使用前,变量能够不赋值
outTest(out a, out b);
Console.WriteLine("a={0};b={1}", a, b);
int
c = 11, d = 22;
outTest(out c, out d);
Console.WriteLine("c={0};d={1}", c, d);
//ref test
int
m, n;
//refTest(ref
m, ref n);
//上面这行会出错,ref使用前,变量必须赋值
int
o = 11, p = 22;
refTest(ref o, ref p);//将ref 关键字去掉 会输出11,22
Console.WriteLine("o={0};p={1}", o, p);
Console
.ReadLine();
}
}
}