You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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);
}

注意事项

  1. unsafe编译选项:确保Unity项目已开启unsafe代码支持——在PlayerSettings中勾选"Allow unsafe code",或在Assembly Definition文件中启用unsafe编译。
  2. 值类型兼容:如果T是值类型,RuntimeHelpers.GetObjectSize同样能返回正确的实例大小,无需额外修改。
  3. 字段范围判断逻辑:该判断仅验证ref指向的字段本身是否属于对象内存范围(而非字段引用的其他对象),符合你“针对对象字段修改做特殊处理”的需求。

内容的提问来源于stack exchange,提问作者Choosechee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 13:10:14