问题描述
void test(Span<int> param)
{
//Fail,the stackalloc'ed buffer Could be exposed.
param = stackalloc int[10];
}
void test2(Span<int> param)
{
//OK
Span<int> local = stackalloc int[10];
}
我不明白为什么 param = stackalloc int[10];
会产生错误:
'Span' 类型的 stackalloc
表达式的结果不能在此上下文中使用,因为它可能会暴露在包含方法之外
Span
是一个 ref struct
但(尽管它的名字)它仍然是一个值类型,所以对 param
的任何修改都不会反映在调用者对象上。
我认为 param
是一个具有初始值的局部变量,我不明白为什么 test2
会编译而 test
不会。
stackalloc int[10]
中 test
的返回值如何脱离方法的作用域?
解决方法
Sinatr 在评论中发布了一个链接 (here the relevant part),帮助我将整个代码置于 Span safety 的上下文中。
在方法 test
中,参数 param
可以安全返回,因为我们可以假装它就像一个局部变量,用调用者给定的值初始化(因此,在方法外部,可以安全返回)。
当一个局部变量被标记为可以安全返回时,编译器将阻止对其进行任何赋值,这些值不能安全返回(stackalloc
表达式可以安全地转义到方法的顶级范围,但不安全显然要回来)。
该方法为 void 的事实并不重要(无论是作为提问者的我,还是编译器),因为这条规则是通用的(我认为处理这些极端情况并没有太大好处)。
为完整起见,此代码无法编译:
void test2(Span<int> param)
{
//Fail,because local is marked safe to return
Span<int> local = param;
local = stackalloc int[10];
}
这是我一直在寻找的缺失部分。