C# ref返回值两种接收方式的差异及底层原理疑问
C# ref返回值的底层运行机制解析
示例代码
FindAuthor方法
public ref string FindAuthor(int number, string[] names) { if (names.Length > 0) return ref names[number]; throw new IndexOutOfRangeException($"{nameof(number)} not found."); }
主方法调用
//main method string[] authors = { "Mahesh Chand", "Mike Gold", "Dave McCarter", "Allen O'neill", "Raj Kumar" }; //first variation string author4 = new Program().FindAuthor(3, authors); Console.WriteLine("Original author:{0}", author4); author4 = "Chris Sells"; Console.WriteLine("Replaced author:{0}", authors[3]); //secondvariation ref string author4 = ref new Program().FindAuthor(3, authors); Console.WriteLine("Original author:{0}", author4); author4 = "Chris Sells"; Console.WriteLine("Replaced author:{0}", authors[3]);
问题核心
FindAuthor方法始终以ref方式返回值,但用普通string author4接收并修改时,原数组无变化;用ref string author4接收修改时,数组会同步改变。为何会有这种差异?
底层运行机制解析
ref返回值的本质:
ref返回的不是变量的值,而是变量在内存中的地址引用。数组元素在内存中连续存储,names[number]指向的是数组对应索引位置的内存地址。普通接收方式的行为:当用普通字符串变量接收ref返回值时,C#会自动解引用该内存地址,把地址里存储的字符串引用拷贝到
author4自己的内存空间。此时author4和数组元素是两个独立变量,修改author4只是让它指向新的字符串对象,完全不会影响原数组元素的内存内容。ref接收方式的行为:用
ref关键字接收时,author4直接绑定到原数组元素的内存地址,相当于原元素的"别名"。对author4的赋值操作,本质是直接修改该内存地址里存储的字符串引用,因此会同步改变原数组。字符串类型的补充说明:虽然字符串是引用类型,但这里的核心差异不在字符串本身——哪怕是值类型数组(比如
int[]),普通接收和ref接收也会产生同样的结果:普通接收拷贝值,ref接收绑定内存地址,修改会影响原数组。
内容的提问来源于stack exchange,提问作者Eric Movsessian
相关产品推荐
相关产品推荐

