在C#中,变量分为两种类型:一种是值类型,另一种是引用类型.任何称为"类"的类型都是引用类型,而任何结构和枚举都是值类型(System.Int32结构,System.DayOfWeek枚举).在方法间传递参数的时候,普通的传递参数都是传值的. 在传递引用类型的对象时,对一个对象的引用会传递给方法.也就是说,目标方法(被调用者)可以修改对象的成员,而源方法(调用者)可以看到这些修改.对于传递值类型的参数,目标方法会获得这个值类型的副本进行处理,而源方法的值类型实例不受到影响.(本段引用 CLR Via C#中的解释)
如果在传递参数的时候,使用ref关键字进行修饰的话,会以传引用的方式传递参数.对于值类型来说,直接把值类型的引用(指针)传递给目标方法,修改结果会影响到源方法中的值类型.但是对于引用类型来说,普通传参已经是传引用了,那么再用ref关键字修饰会是什么样的结果?
public static void Method(StringBuilder param1, ref StringBuilder param2)
{
param1.Append("bb");
param1 = new StringBuilder();
param1.Append("cc");
param2.Append("bb");
param2 = new StringBuilder();
param2.Append("cc");
}
static void Main(string[] args)
{
StringBuilder s1 = new StringBuilder("aa");
StringBuilder s2 = new StringBuilder("aa");
Method(s1, ref s2);
Debug.WriteLine("s1:{0} s2:{1}", s1, s2);
Console.Read();
}
输出:s1:aabb s2:cc
引用类型前不加ref时,只能修改所引用对象的值,而不能对所引用对象的引用进行更改。而在引用类型前加ref时,不仅可以修改所引用对象的值,也可以改变对所引用对象的引用。
理论上值类型和引用类型在运行时存放数据的位置是不同的,值类型的数据是存储在进程的栈(Stack)上的,而引用类型是存储在进程堆(Heap)上的,而进程栈上存储的是这个引用类型在堆上的地址。而某种意义上说,变量不论其类型如何,都是指向某一栈地址的一个标识。
默认情况下,传递给方法参数变量的是栈上的数据,这份数据被拷贝到了参数变量所指向的栈中,而使用ref关键字后,传递的是数据在栈上的地址,参数变量的指向被改变为这个新的栈地址。
对于ref传参,只要记住一点:对于值类型来说传的是值的地址,对于引用类型来说传的是地址的地址。对于引用类型,同样记住一点:引用类型本身的地址是一个值类型。
ref还有一个特例是string
public static void Method(string param1, ref string param2)
{
param1 = param1 + "bb";
param2 = param2 + "bb";
}
static void Main(string[] args)
{
string s1 = "aa";
string s2 = "aa";
Method(s1, ref s2);
Debug.WriteLine("s1:{0} s2:{1}", s1, s2);
Console.Read();
}
输出:s1:aa s2:aabb
在C#中,string是引用类型,但每个string对象都是一个不变的(immutable)Unicode字符串序列。string不变这一事实意味着看似要改变字符串的方法实际上返回的是一个修改后的副本,原字符串在内存中是不变的,直至被垃圾回收。
ref(C# 参考)
http://msdn.microsoft.com/zh-cn/library/14akc2c7.aspx
传递引用类型参数(C# 编程指南
http://msdn.microsoft.com/zh-cn/library/s6938f28.aspx
C#用ref关键字修饰引用型参数传参有何不同
http://www.2cto.com/kf/201204/126068.html
c# 引用类型方法参数的关键字ref深度解析
http://www.cr173.com/html/18225_1.html
C#程序员请不要混淆引用类型和ref引用传参
http://www.cnblogs.com/slmk/archive/2012/03/19/2406429.html
引用类型与ref传递实例精解
http://www.2cto.com/kf/201007/52885.html
图解C#的值类型,引用类型,栈,堆,ref,out
http://www.360doc.com/content/13/0716/09/10504424_300294315.shtml
ref (C#)
http://msdn.microsoft.com/zh-cn/library/14akc2c7(VS.80).aspx