【问题标题】:Span - access to original value跨度 - 访问原始值
【发布时间】:2019-08-04 09:36:19
【问题描述】:

我希望得到一个 Span 代表的原始值。以下面的代码为例,我如何在DoWork 中访问原始字节数组而不创建它的副本

static void Main()
{
    var data = new byte[0x100];
    DoWork(new Span<byte>(data));
}

private void DoWork(Span<byte> Data)
{
    //var data = Data.ToArray(); Unsuitable; creates a copy
    //var data = (byte[])Data; Unsuitable; doesn't work
    //MemoryMarshal. Something in here may work, but unsure
    //MemoryExtensions. Something in here may work, but unsure
}

我发现 2 个带有辅助方法的静态类(如上所示)可能会有所帮助,但我不确定在不让事情变得比制作副本更慢的情况下最好的方法是什么。

【问题讨论】:

  • 跨度是原始值上的一个窗口,可以将其视为指向该字节的指针。因为您有跨度,所以您可以参考实际值。 Data[i] 将为您提供对指定索引的引用或遍历跨度以查看窗口中的所有引用。
  • Span 的全部意义在于为您提供原始数据的抽象视图。对于 DoWork 而言,这将是层违规 1) assume Databyte[] 支持(而不是非托管内存,例如)和 2) 通过封装伸出手来获得在那byte[]。您应该(重新)在DoWork 中编写代码以使用Span,这样您就不需要首先获取“原始字节数组”。如果你确实需要它,那么不要传递Span——传递数组! Span 什么也得不到,而其他代码仍然只在数组上工作。
  • 技术上这是不可能的。跨度包含一个指针,该指针可能指向字节数组的中间。您不能使用该指针并再次找到字节数组的开头。同样,您不能获取该指针并从该指针开始构造一个新数组,而无需复制。
  • 不涉及复制。您正在通过该 Span 查看原始值。为什么不直接使用 Span?为什么要从中创建一个数组?
  • 感谢大家的澄清。

标签: c# .net system.memory


【解决方案1】:

根据Span Document

因为它是一个只有栈的类型,所以 Span 不适合许多需要在堆上存储对缓冲区的引用的场景。例如,对于进行异步方法调用的例程来说,情况就是如此。对于此类场景,您可以使用互补的 System.Memory 和 System.ReadOnlyMemory 类型。

所以也许根据您的需要,您不必使用 Span:

static void Main()
{
    var data = new byte[0x100];
    DoWork(data);
}
private void DoWork(byte[] data)
{
    // data array is by reference.
}

【讨论】:

  • 嗯,也许我可以做一个超载,我想..谢谢你
猜你喜欢
  • 2012-12-25
  • 1970-01-01
  • 2015-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多