您的问题似乎不完整,您是想询问关于C语言编程的某个具体问题吗?比如C语言的语法、编程技巧、项目开发等。请提供更具体的信息,这样我才能给出更准确的回答。

摘要:前言 C# 11 中即将到来一个可以让重视性能的开发者狂喜的重量级特性,这个特性主要是围绕着一个重要底层性能设施 ref 和 struct 的一系列改进。 但是这部分的改进涉及的内容较多,不一定能在 .NET 7(C# 11)做完,因此部分
前言 C# 11 中即将到来一个可以让重视性能的开发者狂喜的重量级特性,这个特性主要是围绕着一个重要底层性能设施 ref 和 struct 的一系列改进。 但是这部分的改进涉及的内容较多,不一定能在 .NET 7(C# 11)做完,因此部分内容推迟到 C# 12 也是有可能的。当然,还是很有希望能在 C# 11 的时间点就看到完全体的。 本文仅仅就这一个特性进行介绍,因为 C# 11 除了本特性之外,还有很多其他的改进,一篇文章根本说不完,其他那些我们就等到 .NET 7 快正式发布的时候再说吧。 背景 C# 自 7.0 版本引入了新的 ref struct 用来表示不可被装箱的栈上对象,但是当时局限性很大,甚至无法被用于泛型约束,也无法作为 struct 的字段。在 C# 11 中,由于特性 ref 字段的推动,需要允许类型持有其它值类型的引用,这方面的东西终于有了大幅度进展。 这些设施旨在允许开发者使用安全的代码编写高性能代码,而无需面对不安全的指针。接下来我就来对 C# 11 甚至 12 在此方面的即将到来的改进进行介绍。 ref 字段 C# 以前是不能在类型中持有对其它值类型的引用的,但是在 C# 11 中,这将变得可能。从 C# 11 开始,将允许 ref struct 定义 ref 字段。 readonly ref struct Span<T> { private readonly ref T _field; private readonly int _length; public Span(ref T value) { _field = ref value; _length = 1; } } 直观来看,这样的特性将允许我们写出上面的代码,这段代码中构造了一个 Span<T>,它持有了对其他 T 对象的引用。 当然,ref struct 也是可以被 default 来初始化的: Span<int> span = default; 但这样 _field 就会是个空引用,不过我们可以通过 Unsafe.IsNullRef 方法来进行检查: if (Unsafe.IsNullRef(ref _field)) { throw new NullReferenceException(...); } 另外,ref字段的可修改性也是一个非常重要的事情,因此引入了: readonly ref:一个对对象的只读引用,这个引用本身不能在构造方法或 init 方法之外被修改 ref readonly:一个对只读对象的引用,这个引用指向的对象不能在构造方法或 init 方法之外被修改 readonly ref readonly:一个对只读对象的只读引用,是上述两种的组合 例如: ref struct Foo { ref readonly int f1; readonly ref int f2; readonly ref readonly int f3; void Bar(int[] array) { f1 = ref array[0]; // 没问题 f1 = array[0]; // 错误,因为 f1 引用的值不能被修改 f2 = ref array[0]; // 错误,因为 f2 本身不能被修改 f2 = array[0]; // 没问题 f3 = ref array[0]; // 错误:因为 f3 本身不能被修改 f3 = array[0]; // 错误:因为 f3 引用的值不能被修改 } } 生命周期 这一切看上去都很美好,但是真的没有任何问题吗? 假设我们有下面的代码来使用上面的东西: Span<int> Foo() { int v = 42; return new Span<int>(ref v); } v 是一个局部变量,在函数返回之后其生命周期就会结束,那么上面这段代码就会导致 Span<int> 持有的 v 的引用变成无效的。顺带一提,上面这段代码是完全合法的,因为 C# 之前不支持 ref 字段,因此上面的代码是不可能出现逃逸问题的。但是 C# 11 加入了 ref 字段,栈上的对象就有可能通过 ref 字段而发生引用逃逸,于是代码变得不安全。
阅读全文