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

C#反射获取类中值类型属性值时出现不等问题的原因

问题:反射获取值类型属性后用!=判定为不同的原因?

我编写了以下代码片段重现遇到的场景,但无法解释观察到的行为:

public class X
{
    public string XS { get; set; }
    public int XN { get; set; }
    public MyEnum Enum { get; set; }
}

void testValueTypesReflectionComparison()
{
    var x1 = new X { XN = 1, XS = "argh", Enum = MyEnum.Component };
    var x2 = new X { XN = 1, XS = "argh", Enum = MyEnum.Component };

    var xTypeProperties = x1.GetType().GetProperties();
    foreach(var property in xTypeProperties)
    {
        var x1PropertyValue = property.GetValue(x1, null);
        var x2PropertyValue = property.GetValue(x2, null);

        if (x1PropertyValue != x2PropertyValue)
        {
            Console.WriteLine($"different values on property: [{property.Name}]: x1: [{x1PropertyValue}] x2: [{x2PropertyValue}]");
        }
    }
}

输出:
输出截图

我在PropertyInfo.GetValue文档中未找到关于获取值类型的特殊说明。为何反射获取的XN和Enum属性值在x1和x2实例中被判定为不同?


解答

  • 核心原因:装箱引发的引用比较
    PropertyInfo.GetValue的返回类型是object,当获取int、枚举这类值类型的属性时,值会被装箱——也就是包装成一个独立的object实例。
    用!=比较两个object时,默认执行的是引用地址比较,而非值比较。即使两个装箱对象的值完全相同,它们也是内存中两个独立的对象,引用地址不同,因此!=会返回true,被判定为“不同”。

  • 字符串为何不受影响?
    字符串属于引用类型,但CLR会对字符串字面量做驻留优化:相同内容的字符串字面量会指向内存中的同一个实例。因此用!=做引用比较时,相同内容的字符串会返回false,不会被判定为不同。

  • 正确的比较方式
    要准确比较属性值,应使用object.Equals(x1PropertyValue, x2PropertyValue)——它会先检查引用是否一致,若不一致则调用对应类型的Equals方法做值比较。修改后的判断代码如下:

if (!object.Equals(x1PropertyValue, x2PropertyValue))
{
    Console.WriteLine($"different values on property: [{property.Name}]: x1: [{x1PropertyValue}] x2: [{x2PropertyValue}]");
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 23:27:26