为何无法将ref struct中同结构体字段的引用赋值给ref字段?
ref struct中CS8374错误的原因解析
先看这段示例代码:
ref struct RefStruct { int _field; ref int _refField; void AssignRef() { _refField = ref _field; // CS8374 无法将“_field”的引用分配给“_refField”,因为“_field”的逃逸范围比“_refField”窄。 } }
文档里明确说明:
编译器确保ref字段中存储的引用不会比其引用对象存活更久。
那为什么把私有_field的引用赋值给_refField会触发错误?哪些情况会导致前者比后者存活更久?
要搞懂这个问题,得先理清ref struct和它的字段的生命周期规则:
- ref struct是栈分配类型,它的生命周期局限于当前方法栈帧(或者它被捕获的闭包范围)。
- ref字段的特殊之处在于:它的引用可以被暴露到ref struct外部(比如通过返回ref的方法传递出去)。
如果允许这种赋值,会出现以下风险场景:
ref struct实例销毁后,_refField的引用仍被使用
假设给RefStruct加一个返回ref的方法:public ref int GetRef() => ref _refField;当RefStruct实例在方法栈帧中被销毁后,之前通过
GetRef()拿到的引用,实际指向的是已经被回收的栈内存(原来的_field所在位置),此时使用这个引用会直接导致内存访问错误。ref字段被传递到更长的作用域
如果把_refField的引用传递到一个比当前ref struct实例生命周期更长的方法或闭包里,当ref struct实例被销毁后,这个引用依然存活,但它指向的_field内存已经被释放,同样会产生悬空引用。
编译器之所以禁止这个赋值,是因为它无法保证_refField的引用不会逃出_field的生命周期范围——_field的生命周期完全绑定到当前ref struct实例,而_refField作为ref字段,其引用的逃逸可能性更大,一旦发生逃逸就会出现无效引用的问题。
内容的提问来源于stack exchange,提问作者Ivan Petrov
相关产品推荐
相关产品推荐

