我可以通过两种方式定义此结构,我希望将其作为参数传递给pinvoke函数。我想知道2
之间有什么区别[StructLayout(LayoutKind.Sequential)]
public struct Rect {
public int left;
public int top;
public int right;
public int bottom;
}
[StructLayout(LayoutKind.Explicit)]
public struct Rect {
[FieldOffset(0)] public int left;
[FieldOffset(4)] public int top;
[FieldOffset(8)] public int right;
[FieldOffset(12)] public int bottom;
}
从我发现here的布局定义来看,内存中的内容看起来不一样吗?一个优于另一个的任何优点?
答案 0 :(得分:5)
根据我在这里找到的布局定义,内存中的内容不应该相同吗?
是的,它们在内存中看起来一样。
一方有什么好处?
输入速度更快,更容易阅读。
使用FieldOffset
当然是一个有用的工具;它并不像总是无用,但是如果你恰好用它来明确地在庄园中布置它们将在默认情况下布局的字段,那么它就没用了。如果您使用它来布置除默认值以外的庄园中的字段(例如,具有重叠,添加填充空间,使基础表示的顺序与声明顺序不同,等等),那么它就没用了
答案 1 :(得分:1)
理论上这两者完全相同。通常,在与非托管代码交互时,您将使用显式布局。 这很重要,因为将来“int”可能没有32位 - 这意味着顺序布局可能不再适用。希望这有点帮助!
修改强>
还有一个想法是,如果您将.NET结构映射到非托管联合或在.NET中使用不同类型而不是非托管代码,这将非常有用。
第二次修改
其他人已经注意到MS将“永远不会”改变int的大小。我同意这将是一个突破性的变化,因此高度不太可能。也就是说,在.NET和非托管代码之间编组值时,明确关于结构映射仍然是个好主意。如果将来有可能出现未管理的结构/布局变化,则尤其如此。
答案 2 :(得分:0)
我不认为这个问题有更好的布局版本。 Explicit
LayoutKind
的第二个版本允许您在使用fieldoffest指示其在内存中的位置时更改结构成员的顺序。
在我看来,第二个版本更容易扩展。