考虑我需要确保类/结构以非常特定的方式映射到内存的情况,可能是由于需要匹配外部协议:
[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
值( - 并且有人指出,由于我不完全理解的原因,实际上无效:
未处理的异常。系统类型加载异常:无法加载类型 程序集"a2bbzf3y.exe的"SYSTEM_INFO2",版本=0.0.0.0, 区域性=中性,公钥令牌=空',因为它包含一个对象 偏移量 0 处的字段未正确对齐或重叠 非对象字段。命令由信号 6 终止
是否可以同时使用这两种方法,其中Buffer
覆盖成员,但除Buffer
之外的所有成员都自动按顺序对齐而不填充?我无法从文档中确定这是否允许,并且我只能在自动决定其他成员的情况下强制某些成员偏移。
在struct
的情况下,您可以非常轻松地执行此操作 - 坦率地说,如果您正在查看字节,您通常应该使用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;
}