【问题标题】:Efficiently convert between equivalent structs in C#在 C# 中的等效结构之间有效转换
【发布时间】:2021-03-03 10:58:41
【问题描述】:

我在两个使用等效结构的库之间进行通信。例如:

struct MyVector {
    public float x, y, z;
}

struct TheirVector {
    public float x, y, z;
}

目前,我通过将每个成员复制到另一个成员的实例中来在这些类型之间“转换”。了解了 C# 如何将结构存储在内存中,难道没有更有效的方法来使用指针吗?

另外,假设我有两个由这些等效结构组成的数组:

MyVector[] array1; // (Length 1000)
TheirVector[] array2; // (Length 1000)

没有办法将整个内存块从array1复制到array2吗?或者更好的是,我可以将整个 array1 视为 array2 类型而不在内存中创建副本吗?

我确定答案需要指针,但我只在 C++ 中使用过指针,不知道 C# 是如何实现它们的。

有没有人有任何例子说明如何实现这样的目标?

提前致谢!

【问题讨论】:

  • 你能使用具有显式布局的联合结构吗?
  • @Charlieface 我不熟悉联合结构。他们具体是做什么的?
  • 具有[StructLayout(LayoutKind.Explicit)] 属性的结构体和其他结构体的两个字段,每个字段都具有[FieldOffset(0)]。您需要确保两个内部结构的布局相互匹配

标签: c# pointers struct casting copy


【解决方案1】:

是的,如果您绝对 100% 确定它们具有相同的内存布局,则可以在它们之间进行强制转换。这样做的首选方法(避免过多的unsafe / 指针)是:spans。例如:

var theirs = MemoryMarshal.Cast<MyVector, TheirVector>(array1);

这将theirs 提供为Span&lt;TheirVector&gt;无需复制任何实际数据。 Spans 具有与数组/向量非常相似的 API,因此您期望的大多数事情:应该完全按照您的期望工作。您只需使用不同类型对同一内存进行类型化引用。

【讨论】:

  • 是否指定了结构的内存布局?如果它依赖于实现,那么我们如何才能 100% 确定内存布局是相同的?
  • @Sweeper 在给出的示例中,我们可以确信它们会兼容;如果你想更加自信,明确的布局属性会很好
  • 内存布局属性啊!我忘了那些!
  • 这适用于 .NET 4.x 吗?我已包含 System.Runtime.InteropServices 命名空间,但找不到 MemoryMarshal 类
  • @LouiEriksson 你需要System.Memory(作为NuGet 包提供):nuget.org/packages/System.Memory - 但是,请注意,span 等的许多最佳功能都不起作用那么好 在 .NET Framework 中(因为缺少 JIT 支持)。坦率地说,现在您应该将 .NET Framework(4.x 等)视为旧版。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多