为什么不能将 `stackalloc` 表达式分配给 `Span<T>` 参数?

问题描述

考虑以下方法 (fiddle):

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];
}

这是我一直在寻找的缺失部分。