为什么ref结构不能用作类型参数?

Fit*_*Dev 8 c# ref-struct c#-7.2

C#7.2 介绍了 ref struct s.但是,考虑到ref struct这样的:

public ref struct Foo {
  public int Bar;
}
Run Code Online (Sandbox Code Playgroud)

我不能将它用作类型参数:

int i = 0;
var x = Unsafe.As<int, Foo>(ref i); // <- Error CS0306 The type 'Foo' may not be used as a type argument.
Run Code Online (Sandbox Code Playgroud)

我知道ref结构只能存在于堆栈中,而不能存在于堆中.但是,如果使用这种引用结构的泛型方法保证永远不会将它们放在堆上,如上面使用System.Runtime.CompilerServices.Unsafe包的示例,该怎么办?为什么我不能在这些情况下使用它们作为类型参数?

Dis*_*ame 7

a 所做的主要保证ref struct是它永远不会逃逸到堆中。

在泛型方法中,编译器不会验证无堆保证(因为几乎所有类型都可以存在于堆上)。防止泛型方法泄漏ref structs 的最直接方法是简单地禁止使用 aref struct作为类型参数,C# 就是这么做的。

从 C# 7.2 开始,可以在结构类型的声明中使用 ref 修饰符。引用结构类型的实例在堆栈上分配,无法逃逸到托管堆。为了确保这一点,编译器限制 ref 结构类型的使用,如下所示:

  • ref 结构体不能是数组的元素类型。
  • 引用结构不能是类字段的声明类型或非引用结构。
  • ref 结构无法实现接口。
  • ref 结构不能装箱到 System.ValueType 或 System.Object。
  • ref 结构不能是类型参数。
  • ref 结构变量不能被 lambda 表达式或本地函数捕获。
  • ref 结构变量不能在异步方法中使用。但是,您可以在同步方法中使用 ref struct 变量,例如,在返回 Task 或 Task.
  • 引用结构变量不能在迭代器中使用。

Microsoft 有关 ref 结构的更多详细信息