我可以得到一个Span <byte>引用非字节类型的结构成员字段吗?

时间:2019-01-31 05:39:04

标签: c#

说我有一个类似下面的结构:

struct MyStruct {
  Guid g;
}

是否可以获得引用该结构字节的Span<byte>

struct MyStruct {
  Guid g;

  public void Foo() {
    Span<byte> bytes = ???
  }
}

bytes就是长度为16的Span<byte>,可以直接读取和写入Guid字段的各个字节。

我可以用不安全的代码做类似的事情,但是似乎现在应该可以通过跨度的安全代码来实现,但是我不知道如何产生跨度。

编辑:澄清一下,我想要一个跨度指向Guid的实际存储位置。含义new Span<byte>(g.ToByteArray))不是我要的。这将分配一个新的数组,将字节复制到该数组,并创建一个引用新分配的数组的Span。通过这样的跨度修改字节不会修改Guid。

3 个答案:

答案 0 :(得分:3)

您可以将Guid强制设置为数组

struct MyStruct {
   public Guid g;
}

...

var s = new MyStruct();
var span = new Span<byte>(s.g.ToByteArray());
span[2] = 4;

注意:以上内容不会修改原始结构。但是,正如您所指出的,您可以使用unsafe

var s = new MyStruct();
var span = new Span<byte>(&s , Marshal.SizeOf(s));

// woah it just become mutable 
span[2] = 4;

答案 1 :(得分:1)

在.Net Core 2.1或更高版本中尝试此操作:

            Span<MyStruct> valSpan = MemoryMarshal.CreateSpan(ref mystruct, 1);
            Span<byte> span = MemoryMarshal.AsBytes(valSpan);

但是要谨慎使用,因为GC可以移动引用类型,所以结构中不应包含任何指针或引用类型。实际上,它会执行运行时检查并抛出异常。

答案 2 :(得分:0)

看看Span类的构造函数,创建Span的唯一方法是提供托管数组或指针。

但是Guid由1个整数,2个短裤和8个字节组成,而不是字节数组。

所以这是不可能的(至少现在不是这样)。