我读过。NET 支持引用返回,但 C # 不支持。有什么特别的原因吗?为什么我不能这样做:
static ref int Max(ref int x, ref int y) { if (x > y) return ref x; else return ref y; }
您所讨论的是返回对值类型的引用的方法。据我所知,C # 中唯一的内置示例是一个值类型的数组访问器:
public struct Point { public int X { get; set; } public int Y { get; set; } }
现在创建一个结构的数组:
var points = new Point[10]; points[0].X = 1; points[0].Y = 2;
在本例中,数组 Indexer返回对 struct 的引用。不可能编写具有相同“返回引用”行为的 自己的索引器(例如自定义集合)。
我没有设计 C # 语言,所以我不知道不支持它背后的所有原因,但我认为简短的答案可能是: 没有它我们也可以很好地处理。
这个问题是 我的博客在2011年6月23日的主题,谢谢你的提问!
C # 团队正在为 C # 7考虑这个问题,详情请参阅 https://github.com/dotnet/roslyn/issues/5233。
更新: 该特性已经进入 C # 7!
你说得对。NET 的确支持对变量的 返回的方法托管引用。.NET 还支持包含对其他变量的托管引用的 局部变量局部变量。(不过,请注意。NET 不支持包含对其他变量的托管引用的 田野或 数组,因为这会使垃圾收集过程过于复杂。此外,“对变量的托管引用”类型是 不可转换为对象,因此不能用作泛型类型或方法的类型参数。)
评论者“ RPM1984”出于某种原因要求引用这一事实。RPM1984我鼓励您阅读 CLI 规范 Partition I Section 8.2.1.1,“ Managedpointers 和相关类型”,以获得关于。NET.
完全可以创建支持这两个特性的 C # 版本。然后你可以做
然后用
int a = 123; int b = 456; ref int c = ref Max(ref a, ref b); c += 100; Console.WriteLine(b); // 556!
根据经验,我知道有可能构建一个支持这些特性的 C # 版本。高级程序员,尤其是那些移植非托管 C + + 代码的人,经常要求我们提供更多类似于 C + + 的能力来处理引用,而不必大费周章地使用指针和到处钉住内存。通过使用托管引用,您可以获得这些好处,而不必付出搞砸垃圾收集性能的代价。
我们已经考虑过这个特性,并且实际上已经实现了足够多的特性,可以向其他内部团队展示以获得他们的反馈。但是在这个时候根据我们的研究 我们认为,这个特性没有足够广泛的吸引力或令人信服的用例来使它成为一个真正受支持的语言特性。我们有更高的优先级和有限的时间和精力,所以我们不会很快做这个功能。
而且,正确地进行这项工作需要对 CLR 进行一些更改。现在 CLR 把返回参数的方法看作是 合法的,而不是 无法证实,因为我们没有检测这种情况的检测器:
ref int M1(ref int x) { return ref x; } ref int M2() { int y = 123; return ref M1(ref y); // Trouble! } int M3() { ref int z = ref M2(); return z; }
M3返回 M2局部变量的内容,但是该变量的生命周期已经结束!可以编写一个检测器来确定明显违反了 没有堆栈安全性的 ref-return 的使用。我们要做的就是编写这样一个检测器,如果检测器不能证明堆栈安全性,那么我们就不允许在程序的这个部分使用 ref 返回。这样做并不需要大量的开发工作,但是对于测试团队来说,确保我们真正得到了所有的用例是一个很大的负担。这只是增加特性成本的另一个因素,以至于目前的收益不会超过成本。
如果您能够向我描述为什么需要这个特性,我将非常感激。我们从真正的客户那里得到的关于他们为什么想要这个产品的信息越多,它就越有可能在某一天成为产品的一部分。这是一个可爱的小功能,我希望能够得到它的客户以某种方式,如果有足够的兴趣。
(另见相关问题 可以在 C # 中返回对变量的引用吗?和 我可以在 C # 函数(如 C + +)中使用引用吗?)
你可以这样做:
public delegate void MyByRefConsumer<T>(ref T val); public void DoSomethingWithValueType(MyByRefConsumer<int> c) { int x = 2; c(ref x); //Handle potentially changed x... }
C # 7.0 支持返回引用。