为何C#7中返回方法内部数组元素的ref返回值可编译且执行正常?
关于C#7 Ref Returns局部数组元素的编译与运行疑问解答
嘿,这个问题确实有点反直觉,我来帮你理清楚背后的原因:
1. 先明确官方规则的核心
按照MSDN的说明,ref返回值不能是方法内的局部变量,因为局部变量在方法执行完毕后会被销毁,返回它的引用会导致悬空引用(访问已回收的内存),这是非常危险的未定义行为,所以编译器会通过CS8168错误来阻止这种操作。
2. 你的代码能编译的关键:编译器优化
你这段代码里的数组string[] array = { "a", "b", "c", "d" };是用常量数组初始化器创建的,而且数组大小很小。C#编译器会对这种情况做特殊优化:它会把这个数组直接分配到程序的静态只读存储区,而不是方法调用的栈帧里。
这意味着这个数组的生命周期不再局限于方法的执行周期,而是和整个程序的生命周期一致——相当于它变成了一个隐含的静态字段,自然满足了“具有方法外部作用域”的要求,所以编译器不会触发CS8168错误。
3. 为什么执行时能拿到正确结果
因为数组被放到了静态存储区,方法返回后它的内存并没有被回收,你返回的ref引用依然指向有效的内存地址,所以能正确读取到字符串内容。但这是依赖编译器优化的行为,并不是所有情况都成立:
- 如果你把数组改成动态创建的形式,比如
string[] array = new string[] { "a", "b", "c", "d" };,编译器就会检测到这是方法内的局部栈分配变量,直接触发CS8168错误。 - 即使当前能运行,这种写法依然是不推荐的——因为优化行为可能随编译器版本、编译选项变化,一旦优化不生效,就会出现悬空引用,导致程序崩溃或不可预测的行为。
4. 正确的Ref Returns用法示例
如果要合法使用ref返回,应该确保返回的引用指向方法外部的变量,比如:
// 类的实例字段 private string[] _array = { "a", "b", "c", "d" }; public ref string CorrectUseRefReturn(int index) { return ref _array[index]; } // 或者方法参数传入的引用 public ref string CorrectUseRefReturn(ref string[] inputArray, int index) { return ref inputArray[index]; }
内容的提问来源于stack exchange,提问作者Coder14
相关产品推荐
相关产品推荐

