C# 11 ref参数逃逸规则疑问:ref int与Span<int>编译差异
为何以下C# 11代码无法编译?
// Example 1 - 编译失败 class C { public Span<int> M(ref int arg) { Span<int> span; span = new Span<int>(ref arg); return span; } }
该代码产生两个编译错误:
error CS9077: 无法通过ref参数返回参数引用的'arg';它只能在return语句中返回。
error CS8347: 无法在此上下文中使用'Span.Span(ref int)'的结果,因为它可能会将参数'reference'引用的变量暴露到其声明范围之外。
我对此感到困惑:代码并未尝试通过ref参数返回arg,也不会将arg引用的变量暴露到其声明范围外。
对比之下,以下两段代码可成功编译:
// Example 2 - 编译成功 class C { public Span<int> M(ref int arg) { Span<int> span = new Span<int>(ref arg); return span; } }
// Example 3 - 编译成功 class C { public Span<int> M(Span<int> arg) { Span<int> span; span = new Span<int>(ref arg[0]); return span; } }
我的直觉是Span<int>内部持有int类型的ref字段,因此示例1和3的逃逸规则应该一致,但实际并非如此。
我用显式持有ref字段的ref struct做了类似实验:
ref struct S { public ref int X; }
以下代码编译失败:
// Example 4 - 编译失败 class C { public S M(ref int arg) { S instance; instance.X = ref arg; return instance; } }
错误信息为:
error CS9079: 无法将'arg' ref赋值给'X',因为'arg'只能通过return语句逃逸当前方法。
对比之下,以下两段代码可成功编译:
// Example 5 - 编译成功 class C { public S M(ref int arg) { S instance = new S() { X = ref arg }; return instance; } }
// Example 6 - 编译成功 class C { public S M(S arg) { S instance; instance.X = ref arg.X; return instance; } }
特别地,若如示例4的错误信息所述,arg只能通过return语句逃逸当前方法,为何示例6中的arg.X不受此限制?
我尝试在C# 11低级结构体改进文档中寻找答案但未成功,且该文档存在多处矛盾。
内容的提问来源于Stack Exchange,提问作者Bartosz
相关产品推荐
相关产品推荐

