【问题标题】:Struct to it's ReadOnlyMemory<byte> representation结构为它的 ReadOnlyMemory<byte> 表示
【发布时间】:2019-03-20 09:20:47
【问题描述】:

我有以下结构:

[StructLayout(LayoutKind.Sequential)]
struct Message
{
     int Header;
     int Data;
}

我想通过网络发送它,而不需要分配(使用SendAsync(ReadOnlyMemory&lt;byte&gt;))调用。

如何从给定的结构中获取Memory&lt;byte&gt;

我最终得到了Span&lt;byte&gt;,然后卡住了。

var message = new Message {
  Header = 1, Data = 3
};
var bytes = MemoryMarshal.AsBytes(
    MemoryMarshal.CreateReadOnlySpan(ref message, 1)
);

有什么方法可以直接将结构放入流中而不进行任何分配?

我在netcoreapp2.1

【问题讨论】:

  • 跨度只能存在于堆栈上。异步方法需要其参数至少与任务本身一样长。因此,如何确保 span 确实存在到任务结束?你不能,因此为什么这些方法使用 Memory,它可以活得更久。这意味着无论如何你都需要复制它。
  • @EtiennedeMartel 我的 message 无论如何都在 AsyncStateMachine 中被捕获 - 它不是 ref struct
  • 总之,标题有误导性。我会更新的。

标签: c# .net-core system.memory


【解决方案1】:

类似:

Span<Message> valSpan = stackalloc Message[1];
valSpan[0] = new Message { Header = 123, Data = 456 };
Span<byte> bytes = MemoryMarshal.Cast<Message, byte>(valSpan); // has length 8

注意我在这里使用Span&lt;T&gt;。如果需要,您可以使用 Memory&lt;T&gt; 做大部分相同的事情 - 但您需要一个支持数组或类似的东西,这通常需要分配 - 如果不是数组,那么自定义 MemoryManager&lt;T&gt;

var arr = new Message[1];
arr[0] = new Message { Header = 123, Data = 456 };
Memory<byte> bytes = MemoryMarshal.Cast<Message, byte>(arr); // has length 8

基本上,你在这里非常接近:

MemoryMarshal.CreateReadOnlySpan(ref message, 1)

不过,诀窍是使用MemoryMarshal.Cast&lt;TFrom, byte&gt;(...) 来获取一个字节跨度。

【讨论】:

  • 很好,但是如果Message 包含引用或指针之类的字段,有什么办法可以做到这一点?假设是byte[] data
  • @joe 您可以将包含引用的数据转换为字节(其中一些基本上没有意义 - 即引用/指针),但您不能再返回 - 基本上,运行时和 CLR 真的 不希望您创建无效的非零引用 - 它会违反整个假设系列。你当然可以用不安全的代码来做,但是....请不要
  • ♦ 为什么没有意义?在许多情况下,我有一个内部带有 intbyte[] object 的结构,我想要一个内存(内存应该保留引用/指针而不是数据本身)。但是在这种情况下我不能做 ref->data bytes。Cast 不允许我这样做。它不能包含引用或指针。我明白我们不应该回去。但是为什么我们有这个前进限制呢?
  • @joe 引用只是具有语义意义的指针,但是......仍然只是随机数字,它们会在每次运行或在运行期间(如果 GC 选择)发生变化,并且不能得到有用的解释;这是显示这样做的代码,所以它是可能的 - 只是......没用:gist.github.com/mgravell/0914818c0f1db594a5e75c631128fe77
  • @joe note 我确实必须降到unsafe 代码才能作为跨度返回;不过,您可以做到这一点 - gist.github.com/mgravell/1e65d60e8c21b0de18137fa39688fe25
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-08
  • 2019-02-03
  • 1970-01-01
  • 1970-01-01
  • 2020-04-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多