值类型相等性与强名称程序集下Mocked.Point相等判断异常问题
问题原因
核心原因是值类型默认内存布局的差异和memcmp的全字节对比逻辑冲突,具体拆解如下:
- 首先,.NET中结构体的默认
StructLayout是LayoutKind.Auto,CLR会自动调整字段内存排列、插入对齐填充字节来优化CPU访问效率,且自动布局的规则会根据结构体的字段总数、字段类型动态变化。你提到Original.Point有多个Mocked.Point不存在的属性/方法,如果这些属性是实例自动属性,会生成对应的隐藏后台字段,进一步拉大两个结构体的内存布局差异。 ValueType.FastEqualsCheck调用的memcmp会对比值类型占据的全部内存字节,不止是你可见的X/Y/Z三个float字段,还包括CLR插入的填充字节、Original.Point特有的隐藏字段对应的内存空间。- 案例A中:
a是未被Mock的Host程序集用Original.Point的内存布局初始化的,除了X/Y/Z之外的内存空间存储的是Original.Point的隐藏字段值、或者符合Original.Point布局规则的填充值;而你自己new出来的b是按Mocked.Point的布局初始化的,额外内存空间都是.NET默认清零的填充值,两部分字节不匹配,自然memcmp返回false。 - 案例B中:两个实例都是按
Mocked.Point的规则初始化,内存布局完全一致,填充字节也都是默认的0,所以memcmp返回true。
临时解决方案
你可以通过以下方式规避该问题:
- 给
Mocked.Point显式指定[StructLayout(LayoutKind.Sequential)],如果能拿到Original.Point的内存偏移信息,也可以用LayoutKind.Explicit给每个字段指定和原始类型完全一致的偏移量。 - 重写
Mocked.Point的Equals方法和==运算符,主动只对比X/Y/Z三个字段的值,不走ValueType的默认相等性判断逻辑。
内容的提问来源于stack exchange,提问作者Timo
相关产品推荐
相关产品推荐

