首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在List<float>中解析byte[]并在不分配内存的情况下将其复制到其他数组

在List<float>中解析byte[]并在不分配内存的情况下将其复制到其他数组
EN

Stack Overflow用户
提问于 2022-09-28 10:14:40
回答 2查看 59关注 0票数 0

我有一个类,它包含两个大小相同的列表,需要转换为byte[]并将它们复制到另一个数组中。

实际上,我使用了以下代码:

代码语言:javascript
运行
复制
var lenght = MyObject.firstList[i].Count;
for (var i = 0; i < MyObject.firstList.Count; i++)
{
      BitConverter.GetBytes(MyObject.firstList[i]).CopyTo(bytes, i * sizeof(float));
      BitConverter.GetBytes(MyObject.secondList[i]).CopyTo(bytes, i * sizeof(float) + lenght * sizeof(float));
}

这段代码的问题是,它总是分配大量内存,导致** GC *进行干预。

如何在不进行过多内存分配的情况下优化代码。是否有使用不安全IntPtrSpan的最佳解决方案?

我尝试使用这个解决方案,但是出现了错误

System.AccessViolationException:‘试图读取或写入受保护的内存。这通常表明其他内存

前提:

  • 我不能用float[]代替List
EN

Stack Overflow用户

发布于 2022-09-28 15:11:38

BitConverter.GetBytes为每个转换的值创建一个新的字节数组,因此如果您经常使用此方法而不打算保留这些字节数组,则GC最终必须收集所有这些字节数组实例。

另一种不依赖于创建“临时”数组的方法是使用Span (Span)。现在,由于我们处理的是List而不是数组,所以将使用CollectionsMarshal.AsSpan方法在List实例(即List实例中包含的数据)内部私有数组的使用部分上获得一个Span。

但是,这里处理的列表是List实例,因此产生的Span是一个span。Span不能直接复制到字节数组(即Span)中。因此,Span将被转换为使用MemoryMarshal.Cast的Span。这样,列表内容的Span可以简单地复制到目标字节数组中:

代码语言:javascript
运行
复制
using System.Runtime.InteropServices;

var bytes = new byte[(MyObject.firstList.Count + MyObject.secondList.Count) * sizeof(float)];

var list1AsByteSpan = MemoryMarshal.Cast<float, byte>(
    CollectionsMarshal.AsSpan(MyObject.firstList)
);

var list2AsByteSpan = MemoryMarshal.Cast<float, byte>(
    CollectionsMarshal.AsSpan(MyObject.secondList)
);

list1AsByteSpan.CopyTo(bytes);
list2AsByteSpan.CopyTo(bytes.AsSpan(MyObject.firstList.Count * sizeof(float)));

(请注意,单个浮动值的字节顺序取决于运行代码的主机系统CPU体系结构的安全性。)

我鼓励您阅读CollectionsMarshal.AsSpan和MemoryMarshal.Cast方法的链接文档,以便了解它们可能对它们的使用造成的任何限制(特别是在CollectionsMarshal.AsSpan方面)。如果您决定只复制“n”粘贴我的代码而不阅读文档,我认为这是完全没有问题的,但是忽略您可能会做的文档将是您自己的危险……;-)

票数 -1
EN
查看全部 2 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73879731

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档