在撰写这篇文章的时候,C# 7的新特性都还处于提案阶段。它们可能会改变形态,或者可能不会在C# 7中实现,甚至可能永远不会实现。每篇文章都会包含指向GitHub上提案问题的链接,这样就可以跟进关于这些特性的持续讨论。
对于C#来说,这是一个有趣的时期。语言的下一个版本正在公开设计中,团队成员和社区的评论和讨论将决定应该向语言添加哪些特性。
这个提案为C#添加了通过引用从方法返回值的支持。此外,局部变量可以被声明为‘ref’变量。一个方法可以返回对内部数据结构的引用。与返回一个副本不同,返回值将是指向内部存储的引用:
ref PhysicalObject GetAsteroid(Position p) {
int index = p.GetIndex();
return ref Objects[index];
}
ref var a = ref GetAsteroid(p);
a.Explode();
一旦语言定义了ref返回值,自然地也会拥有ref局部变量,以便通过引用引用堆分配的存储:
ref PhysicalObject obj = ref Objects[index];
这使得在不需要使用不安全代码(指向固定内存的指针)的情况下,可以传递对内部结构的引用。这些机制既不安全也不高效。
通过引用返回值可以在替代方案是固定内存或复制资源的情况下提高性能。这个特性使得开发者可以继续使用可验证的安全代码,同时避免不必要的副本。
这可能不是每天都会使用的特性,但对于需要大量内存的不同结构的算法来说,这个特性可以对应用程序性能产生显著的积极影响。
围绕这个特性的一个有趣的设计挑战是确保返回的引用在返回后仍然可达。编译器将确保由ref返回的对象在方法退出后仍然可达。如果对象将不可到达,并且可能会被垃圾回收,那将导致编译器错误。
实际上,这意味着不能返回对局部变量的ref,或者对不是ref参数的参数的ref。在GitHub评论中有一段很长的讨论,详细讨论了编译器如何推理任何将通过引用返回的对象的生命周期。
实现引用返回和局部变量需要编译器和运行时的紧密合作。编译器需要能够跟踪对象的生命周期,并确保在方法调用结束后,返回的引用仍然有效。这涉及到复杂的内存管理和生命周期分析。
在运行时,需要确保对象不会被垃圾回收器过早地回收。这可能需要引入新的内存屏障和同步机制,以确保对象在需要时仍然可用。
引用返回和局部变量的主要优势在于性能。在处理大型数据结构时,避免复制可以显著减少内存使用和提高处理速度。例如,在图形渲染、科学计算和大数据处理等领域,这种特性可以提供显著的性能提升。
然而,这种性能提升需要开发者仔细设计代码,以确保不会引入新的内存泄漏或数据竞争问题。正确使用这些特性需要对C#的内存管理和并发模型有深入的理解。
尽管引用返回和局部变量提供了性能优势,但它们也引入了新的安全挑战。开发者需要确保不会意外地修改不应该被修改的数据,或者在不正确的上下文中访问数据。
为了确保安全,C#团队可能会引入新的安全特性,如引用透明性、引用安全性检查和更严格的生命周期分析。这些特性将帮助开发者编写更安全、更可靠的代码。
C#7的这些新特性展示了语言的持续发展和对现代编程需求的适应。随着硬件和软件环境的变化,C#需要不断进化,以满足开发者的需求。