C# 如果使用FieldOffset,则必须在每个类/结构成员上使用它吗?

C# 如果使用FieldOffset,则必须在每个类/结构成员上使用它吗?,c#,marshalling,structlayout,C#,Marshalling,Structlayout,考虑这样一种情况,我需要确保类/结构以非常特定的方式映射到内存,这可能是因为需要匹配外部协议: [StructLayout(LayoutKind.Sequential, Pack=1)] public class SYSTEM_INFO { public ulong OemId; public ulong PageSize; public ulong ActiveProcessorMask; public ulong NumberOfProcessors; public ulong P

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

[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,版本=0.0.0.0”的“SYSTEM_INFO2”, Culture=neutral,PublicKeyToken=null'因为它包含一个对象 偏移量为0的字段未正确对齐或重叠 非对象字段。命令被信号6终止


如果
Buffer
覆盖了成员,但除了
Buffer
之外的所有成员都会自动按顺序对齐,而不进行填充,是否可以将这两种方法结合使用?我无法从文档中判断这是否允许,我可以强制某些成员偏移,而其他成员偏移只能自动决定

对于
struct
,您可以很容易地做到这一点——坦率地说,如果您查看字节,通常应该使用
struct

使用系统;
使用System.Runtime.CompilerServices;
使用System.Runtime.InteropServices;
静态P类
{
静态void Main()
{
var obj=新系统信息();
var字节=AsBytes(参考obj);
Console.WriteLine(bytes.Length);//40
}
静态跨度为字节(参考T值)
=>MemoryMarshal.CreateSpan(
参考值As(参考值),
不安全。SizeOf());
}
公共只读结构SystemInfo
{
公共只读ulong OemId;
公共只读ulong页面大小;
公共只读ulong ActiveProcessorMask;
公共只读ulong NumberOfProcessor;
公共只读ulong ProcessorType;
}

Overlay是正确的术语。我认为如果你有一个基类和一个继承基类的类,你可以创建一个覆盖。若要使用FieldOffset,则只能使用LayoutKind.Explicit,然后每个属性必须具有FieldOffset。
[40]
不会编译(C#7.3)。我认为您需要
[marshallas(UnmanagedType.ByValArray,SizeConst=40)]
[FieldOffset(0),marshallas(UnmanagedType.ByValArray,SizeConst=40)]公共字节[]缓冲区我不确定第一个参数。@Amy我相信他们更希望它是一个“固定缓冲区”,恰好跨越整个对象:
公共固定字节缓冲区[40]@MarcGravel我在这里听从你的智慧,老实说,我在编组方面的经验相当薄弱。我应该删除我的评论吗?@Amy我不会(删除它),因为我很确定其他读者也会有同样的想法,所以它有助于保留上下文/澄清。这是一种有趣的方法,但似乎回避了问题,而不是直接回答问题,而是支持另一种方法。这是受欢迎的,但我仍然对一个更直接的答案感到好奇——这是我从未与之合作过的C#的整个方面