我怎样才能获得 Span<T>来自列表 <T>同时避免不必要的副本? [英] How can I get a Span<T> from a List<T> while avoiding needless copies?
问题描述
我有一个包含一些数据的 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<T>来自列表 <T>同时避免不必要的副本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!