为什么以下代码在 C# 11 中无法编译?
// Example 1 - fails
class C {
public Span<int> M(ref int arg) {
Span<int> span;
span = new Span<int>(ref arg);
return span;
}
}
Run Code Online (Sandbox Code Playgroud)
它产生两个编译错误:
错误CS9077:无法通过 ref 参数通过引用“arg”返回参数;它只能在 return 语句中返回。
错误 CS8347:无法在此上下文中使用“Span.Span(ref int)”的结果,因为它可能会在其声明范围之外公开参数“reference”引用的变量。
它们对我来说都没有意义:我的代码不会尝试arg通过 ref 参数返回,并且它不能公开arg其声明范围之外引用的变量。
对比之下,下面两段代码编译成功:
// Example 2 - succeeds
class C {
public Span<int> M(ref int arg) {
Span<int> span = new Span<int>(ref arg);
return span;
}
}
Run Code Online (Sandbox Code Playgroud)
// Example 3 - succeeds
class C {
public Span<int> M(Span<int> arg) {
Span<int> span;
span = new Span<int>(ref arg[0]);
return span;
}
}
Run Code Online (Sandbox Code Playgroud)
我的直觉是,Span<int>内部保存了一个 ref 类型的字段int,因此转义规则对于上面的示例 1 和 3 应该是相同的(显然,它们不是)。
我使用显式保存 ref 字段的 ref 结构进行了类似的实验:
ref struct S {
public ref int X;
}
Run Code Online (Sandbox Code Playgroud)
现在,以下代码无法编译:
// Example 4 - fails
class C {
public S M(ref int arg) {
S instance;
instance.X = ref arg;
return instance;
}
}
Run Code Online (Sandbox Code Playgroud)
它会产生以下错误,这至少对我来说更有意义:
错误 CS9079:无法将“arg”引用分配给“X”,因为“arg”只能通过 return 语句转义当前方法。
对比之下,下面两段代码编译成功(具有上面的定义S):
// Example 5 - succeeds
class C {
public S M(ref int arg) {
S instance = new S() { X = ref arg };
return instance;
}
}
Run Code Online (Sandbox Code Playgroud)
// Example 6 - succeeds
class C {
public S M(S arg) {
S instance;
instance.X = ref arg.X;
return instance;
}
}
Run Code Online (Sandbox Code Playgroud)
特别是,如果只能通过 return 语句转义当前方法,如上面示例 4 的错误消息所示,而示例 6 中arg不也是如此吗?arg.X
我试图在低级结构改进的文档中找到答案,但失败了。此外,该文档页面似乎在几个地方自相矛盾。