C#中带ref参数的ref return方法嵌套调用返回报错如何解决?
问题原因
这是C#内置的ref安全生命周期校验规则导致的:
- 当一个带
ref return的方法接收了ref/in/out类型的参数时,编译器会默认假设该方法返回的引用和传入的ref参数生命周期绑定,返回的引用不能比输入的ref参数存活更久。 - 你在
Get2中传入Get方法的someParam2是Get2的局部变量,生命周期会在Get2执行结束时销毁。编译器判定你要返回的result引用和这个局部变量绑定,返回后会变成悬垂引用,因此抛出CS8157错误。 - 第二个可正常运行的示例中,
Get方法没有任何ref类型的入参,编译器可以识别到它返回的引用指向类的实例字段,生命周期和类实例绑定,远长于Get2的执行周期,因此不会触发校验错误。
解决方案
如果你使用的是.NET 7及以上版本,可以通过给Get方法的返回值标注UnscopedRef特性,明确告知编译器:该方法返回的引用生命周期不受输入ref参数的限制,可以安全向外返回:
using System.Diagnostics.CodeAnalysis; public class TestRef { public int storage = 42; [return: UnscopedRef] public ref int Get(ref bool someParam) { return ref this.storage; } public ref int Get2(bool someParam) { bool someParam2 = someParam; return ref Get(ref someParam2); } }
如果使用低于.NET 7的版本,且必须保留Get方法的ref入参,可以考虑将作为参数传递的局部变量提升为类的字段,避免生命周期被限制在方法内,不过该方案会改变类的结构,非必要不推荐使用。
注意:标注
UnscopedRef之后编译器会跳过对应的生命周期校验,你需要自行保证返回的引用确实比传入的ref参数存活更久,否则可能出现无法预期的悬垂引用问题。
内容的提问来源于stack exchange,提问作者JasonS
相关产品推荐
相关产品推荐

