<byte> 从临时字节 [] 返回 Span 是否危险(可能会在使用时生成异常)?



在.NET Core 3.0项目中,我有一个返回Span<byte>的接口。这适用于一大组类,除了一个特定的实现,它可以动态生成其数据(由于没有缓存它(。

实现如下所示:

public Span<byte> Data => CompileBytes();

它会像这样(这是抽象代码,但非常接近用例(

public byte[] CompileBytes()
{
using (MemoryStream stream = new MemoryStream())
{
foreach (IDataSource data in DataSources)
stream.Write(data.ByteArray);
return stream.ToArray();
}
}

我一直在网上寻找,看看是否有保证这是安全的,但没有找到。

我担心的是,Span是GC将忽略的数据周围的非常薄的一层,因此GC假设我们不会让跨度超过底层缓冲区,并且创建的临时字节数组最终将获得GC'd,这意味着如果由于某种原因,当其他代码正在使用跨度时,我可能会有一个滴答作响的定时炸弹。是这样吗?我可以为临时对象返回一个Span<>并且完全没问题(假设它通过保持在跨度的范围内被正确使用(?

该定义似乎依赖于实现,因此我无法以我有限的知识弄清楚它是否保留了引用......因为如果是这样,那么我就安全了,我的问题得到了回答。

MSDN 说"内存安全",但我不确定他们定义内存安全的确切细节以及它是否涵盖我的定义。因此,如果是这样,那么这个问题就得到了回答。

我没有使用任何unsafe代码。

Span<T>中引用托管数组是安全的,即使它是对它的唯一引用。
如文章 关于跨度:探索新的 .NET 支柱中所述,Span<T>使用一种特殊的方式来存储这些引用,即ByReference<T>,它作为 JIT 内部函数实现。

引用链接的文章(如何实现Span<T>部分?

Span<T>实际上是为了在运行时中使用一个特殊的内部类型而编写的,该类型被视为实时 (JIT( 内部类型,JIT 为其生成相当于 ref T 字段

和部分什么是Memory<T>,你为什么需要它?

Span<T>是一种类似 ref 的类型,因为它包含一个 ref 字段,并且 ref 字段不仅可以引用数组等对象的开头,还可以引用它们的中间 [...]这些引用称为内部指针,对于 .NET 运行时的垃圾回收器来说,跟踪它们是一项相对昂贵的操作。

该引用的最后一部分阐明了存储在Span<T>中的引用确实由 GC 跟踪,因此它不会清理仍在引用的内存

最新更新