2

考虑我需要确保以非常特定的方式将类/结构映射到内存的情况,可能是由于需要匹配外部协议:

[StructLayout(LayoutKind.Sequential, Pack=1)]
public class SYSTEM_INFO
{
 public ulong OemId;
 public ulong PageSize;
 public ulong ActiveProcessorMask;
 public ulong NumberOfProcessors;
 public ulong ProcessorType;
}

然后我考虑做一个“覆盖”(这是一个合适的术语吗?),所以我可以直接访问内存:

[StructLayout(LayoutKind.Explicit)]
public class SYSTEM_INFO
{
[FieldOffset(0)] public byte[] Buffer = new byte[40]; //overlays all the bytes, like a C union
[FieldOffset(0)] public ulong OemId;
[FieldOffset(8)] public ulong PageSize;
[FieldOffset(16)] public ulong ActiveProcessorMask;
[FieldOffset(24)] public ulong NumberOfProcessors;
[FieldOffset(32)] public ulong ProcessorType;
}

但这会变得耗时且容易出错(如果发生变化,我很容易搞砸更新所有FieldOffset值) - 并且由于我不完全理解的原因而被指出实际上是无效的:

未处理的异常。System.TypeLoadException:无法从程序集“a2bbzf3y.exe,Version=0.0.0.0,Culture=neutral,PublicKeyToken=null”加载类型“SYSTEM_INFO2”,因为它包含偏移量 0 处的对象字段,该对象字段未正确对齐或重叠-对象字段。命令由信号 6 终止

是否可以结合使用这两种方法,其中Buffer覆盖成员,但除了所有成员之外 Buffer的所有成员都自动按顺序对齐而没有填充?我无法从文档中找出是否允许这样做,并且我只能强制某些成员偏移,而其他成员会自动决定。

4

1 回答 1

2

在 a 的情况下struct,你可以很容易地做到这一点 - 坦率地说,如果你正在查看字节,你通常应该使用 a struct

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

static class P
{
    static void Main()
    {
        var obj = new SystemInfo();
        var bytes = AsBytes(ref obj);
        Console.WriteLine(bytes.Length); // 40
    }

    static Span<byte> AsBytes<T>(ref T value)
        => MemoryMarshal.CreateSpan(
            ref Unsafe.As<T, byte>(ref value),
            Unsafe.SizeOf<T>());
}

public readonly struct SystemInfo
{
    public readonly ulong OemId;
    public readonly ulong PageSize;
    public readonly ulong ActiveProcessorMask;
    public readonly ulong NumberOfProcessors;
    public readonly ulong ProcessorType;
}
于 2020-01-27T16:49:30.467 回答