我怎样才能获得 Span<T>来自列表 <T>同时避免不必要的副本? [英] How can I get a Span<T> from a List<T> while avoiding needless copies?

查看:43
本文介绍了我怎样才能获得 Span<T>来自列表 <T>同时避免不必要的副本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含一些数据的 List.我想将它传递给一个接受 ReadOnlySpan 的函数.

I have a List<T> containing some data. I would like to pass it to a function which accepts ReadOnlySpan<T>.

List<T> items = GetListOfItems();
// ...
void Consume<T>(ReadOnlySpan<T> buffer)
// ...
Consume(items??);

在这个特定的例子中,T 是 byte 但这并不重要.

In this particular instance T is byte but it doesn't really matter.

我知道我可以在 List 上使用 .ToArray(),并构造一个跨度,例如

I know I can use .ToArray() on the List, and the construct a span, e.g.

Consume(new ReadOnlySpan<T>(items.ToArray()));

然而,这会创建一个(看似)不必要的项目副本.有没有办法直接从列表中获取跨度?List<T> 是根据T[] 在幕后实现的,所以理论上是可能的,但就我在实践中看到的而言不是?

However this creates a (seemingly) unneccessary copy of the items. Is there any way to get a Span directly from a List? List<T> is implemented in terms of T[] behind the scenes, so in theory it's possible, but not as far as I can see in practice?

推荐答案

在 .Net 5.0 中,您可以使用 CollectionsMarshal.AsSpan() (source, GitHub isue) 以获取 List 的底层数组作为 Span.

In .Net 5.0, you can use CollectionsMarshal.AsSpan() (source, GitHub isue) to get the underlying array of a List<T> as a Span<T>.

请记住,这仍然不安全:如果 List 重新分配数组,CollectionsMarshal.AsSpan 之前返回的 Span 不会反映对 List 的任何进一步更改.(这就是该方法隐藏在 System.Runtime.InteropServices.CollectionsMarshal 类中的原因.)

Keep in mind that this is still unsafe: if the List<T> reallocates the array, the Span<T> previously returned by CollectionsMarshal.AsSpan won't reflect any further changes to the List<T>. (Which is why the method is hidden in the System.Runtime.InteropServices.CollectionsMarshal class.)

这篇关于我怎样才能获得 Span&lt;T&gt;来自列表 &lt;T&gt;同时避免不必要的副本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆