可以在 ref 结构中初始化 Span<T> 字段吗?

Posted

技术标签:

【中文标题】可以在 ref 结构中初始化 Span<T> 字段吗?【英文标题】:It is possible to initialize a Span<T> field in a ref struct? 【发布时间】:2021-06-18 07:31:29 【问题描述】:

这不起作用,因为您不能直接初始化结构中的字段:

public ref  struct WordCollection
         
        public Span<byte> words = stackalloc byte[100];
    

错误是:“WordCollection”:结构中不能有实例属性或字段初始值设定项。

但是,我也无法使用构造函数对其进行初始化:

public ref  struct WordCollection
         
        public Span<byte> words;

        public WordCollection(int size)
        
            words = stackalloc byte[size];
        
    

这里的错误是:在将控制权返回给调用者之前,必须完全分配字段“WordCollection.words”。

这也行不通:

public ref  struct WordCollection
         
        public Span<byte> words;
    

public class Test
    
       public static void WordProc()
        
            WordCollection wordCollection = new WordCollection();
            wordCollection.words = stackalloc byte[100];
         
    

错误是:'Span' 类型的 stackalloc 表达式的结果不能在此上下文中使用,因为它可能暴露在包含方法之外。

那么,问题是:可以初始化一个引用结构的Span&lt;T&gt; 字段吗?

【问题讨论】:

我看到的中间代码错误与您在此处引用的完全不同。 because it may be exposed outside of the containing method. 从字面上告诉你问题:你不能在结构的构造中的任何地方stackalloc 因为一旦你返回调用者它就会消失(它是一个 stack毕竟分配)@JonSkeet 在他的回答中是正确的,你必须从调用者方法传递Span 有趣的是,编译器允许new WordCollection words = stackalloc byte[100] ,这似乎不一致。至少,对象初始值设定项的定义中没有任何内容可以解释为什么在不允许单独赋值的情况下允许这样做。 【参考方案1】:

这可能不是最好的方法,但您可以将 Span&lt;byte&gt; 传递给构造函数:

public ref struct WordCollection

    public Span<byte> words;

    public WordCollection(Span<byte> words)
    
        this.words = words;
    

然后:

class Program

    static void Main(string[] args)
    
        Console.WriteLine("Hello World!");
        WordCollection words = new WordCollection(stackalloc byte[100]);
    

这真的取决于你想用它做什么......

【讨论】:

只是想:为什么案例 #3 不起作用?它被声明为ref struct,所以编译器知道它不会逃跑 @Charlieface:恐怕这个的微妙之处超出了我的范围。我一直觉得ref struct 部分很难理解:(【参考方案2】:

我发现这是可行的:

public ref  struct WordCollection
         
        public Span<byte> words;
    

public class Test
    
       public static void WordProc()
        
            WordCollection wordCollection = new WordCollection 
                wordCollection.words = stackalloc byte[100]
            ;
         
    

这有点奇怪,不是我喜欢的方式,但可以完成工作。

【讨论】:

这不能编译; wordCollection.words 在初始化程序中使用是不合法的。只是words 是。

以上是关于可以在 ref 结构中初始化 Span<T> 字段吗?的主要内容,如果未能解决你的问题,请参考以下文章

站在前人的肩膀上重新透视C# Span<T;数据结构

[react] react中可以在render访问refs吗?为什么?

我在哪里可以找到新的 Span<T>?

C# 中的 ref 已经被放开,或许你已经不认识了

vue通过ref获取dom节点

如何表示 Span<T> 列表/数组