在C#中如何检查引用是否指向特定对象的字段?(Unity mod开发场景)
解决Unity Mod框架中托管对象实际内存大小获取问题
要判断ref字段是否属于指定对象的内存范围,核心问题是获取托管对象实例的实际内存大小——Unsafe.SizeOf<T>()仅返回引用类型的引用大小(通常8字节),无法满足需求,这里可以用RuntimeHelpers.GetObjectSize方法解决:
核心修改点
System.Runtime.CompilerServices.RuntimeHelpers.GetObjectSize会返回托管对象实例在堆中占用的总字节数(包括对象头和实例字段),且针对子类实例会返回实际大小,完美适配你“无法预先知晓子类类型”的场景。
修改后的构造函数代码:
using System.Runtime.CompilerServices; public unsafe TemporaryChangeField(T fieldOwner, ref U changedField) { long* fieldOwnerPtr = (long*)Unsafe.AsPointer(ref fieldOwner); byte* fieldOwnerStart = (byte*)*fieldOwnerPtr; // 替换为RuntimeHelpers.GetObjectSize获取实例实际大小 byte* fieldOwnerEnd = fieldOwnerStart + RuntimeHelpers.GetObjectSize(fieldOwner); byte* changedFieldPtr = (byte*)Unsafe.AsPointer(ref changedField); Console.WriteLine((long)fieldOwnerStart); Console.WriteLine((long)fieldOwnerEnd); Console.WriteLine((long)changedFieldPtr); if (!(changedFieldPtr >= fieldOwnerStart && changedFieldPtr <= fieldOwnerEnd)) throw new ArgumentException("Field specified is not contained in the specified field owner", nameof(changedField)); this.fieldOwner = fieldOwner; this.changedField = new Ref<U>(fieldOwner, ref changedField); }
注意事项
- unsafe编译选项:确保Unity项目已开启unsafe代码支持——在PlayerSettings中勾选"Allow unsafe code",或在Assembly Definition文件中启用unsafe编译。
- 值类型兼容:如果
T是值类型,RuntimeHelpers.GetObjectSize同样能返回正确的实例大小,无需额外修改。 - 字段范围判断逻辑:该判断仅验证
ref指向的字段本身是否属于对象内存范围(而非字段引用的其他对象),符合你“针对对象字段修改做特殊处理”的需求。
内容的提问来源于stack exchange,提问作者Choosechee
相关产品推荐
相关产品推荐

