与这个答案中评论的有同样的困惑。
摘自 CleanCoder:
Marshal.OffsetIf 可以用于结构体中的字段/属性吗?这需要如何命名?让我们说:Struct1.Struct2.Prop1 Strct1 中 Prop1 的标识符是什么? 我想获取成员的非托管偏移量,该成员是父结构内子结构的成员。需要明确的是:嵌套成员相对于 topmost 结构的偏移量。
我尝试了
offset2
方法(见下面的代码),它可以给我正确的偏移量,但我想知道是否有更好的方法?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
struct Address
{
public int Building;
public int Room;
}
struct Person
{
public int Age;
public int Height;
public Address Addr;
}
class OffsetTest
{
public static void CalOffset()
{
// OK
int offset1 = (int)Marshal.OffsetOf(typeof(Person), nameof(Person.Addr));
// Ok, manual add offsets (recursively if nested layer is deeper)
int offset2 = (int)Marshal.OffsetOf(typeof(Person), nameof(Person.Addr)) + (int)Marshal.OffsetOf(typeof(Address), nameof(Address.Room));
// Exception as expected: System.ArgumentException:“Field passed in is not a marshaled member of the type 'Person'. Arg_ParamName_Name”
int offset3 = (int)Marshal.OffsetOf(typeof(Person), nameof(Person.Addr.Room));
// Exception, too
int offset4 = (int)Marshal.OffsetOf(typeof(Person), "Addr.Room");
}
}
在C++中,我会考虑创建一个对象并通过直接减去地址来计算偏移量,但在C#中我不知道该怎么做。
可以用于结构体中的字段/属性吗?这需要如何命名?Marshal.OffsetOf
不。它接受应该出现在提供的类型中的字段名称,而不是路径。来自
Marshal.OffsetOf
文档:
参数
fieldName
String
T类型中字段的名称。
因此,您将需要手动计算偏移量(就像您在“手动添加偏移量(如果嵌套层更深,则递归地)”中所做的那样)。如果需要,您可以将其包装到一些方便的(扩展)方法中,该方法将接受“路径”并使用一些缓存的反射来确定偏移量。
附注
请注意,
nameof(Person.Addr.Room)
是 "Room"
。