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

如何比较未知类型对象的类型与属性值是否完全一致?

实现对象属性值的深度比较方法

需求说明

需要编写一个通用方法,比较两个未知类型的对象:

  • 当二者类型完全相同且所有公共属性值一致时返回True
  • 否则返回False
  • 不重写对象的Equals方法,保留原有==运算符的默认行为
  • 用于从对象集合中匹配属性值一致的元素,对象不一定是同一类型或实例

实现代码

以下是包含递归处理、循环引用防护的完整实现:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;

public static class ObjectComparer
{
    public static bool CheckEqual(object a, object b)
    {
        // 处理null情况:都为null返回true,一个为null返回false
        if (ReferenceEquals(a, b))
            return true;
        if (a == null || b == null)
            return false;

        // 类型不同直接返回false
        if (a.GetType() != b.GetType())
            return false;

        // 处理值类型和字符串(值类型直接用==比较,字符串特殊处理)
        if (a is ValueType || a is string)
            return a.Equals(b);

        // 处理集合类型
        if (a is IEnumerable enumerableA && b is IEnumerable enumerableB)
        {
            var enumeratorA = enumerableA.GetEnumerator();
            var enumeratorB = enumerableB.GetEnumerator();
            
            bool hasNextA, hasNextB;
            while ((hasNextA = enumeratorA.MoveNext()) && (hasNextB = enumeratorB.MoveNext()))
            {
                if (!CheckEqual(enumeratorA.Current, enumeratorB.Current))
                    return false;
            }
            // 两个集合元素数量必须一致
            return hasNextA == hasNextB;
        }

        // 用哈希集合跟踪已比较的对象,防止循环引用导致无限递归
        var comparedObjects = new HashSet<Tuple<object, object>>();
        return DeepCompareProperties(a, b, comparedObjects);
    }

    private static bool DeepCompareProperties(object a, object b, HashSet<Tuple<object, object>> comparedObjects)
    {
        var tuple = Tuple.Create(a, b);
        if (comparedObjects.Contains(tuple))
            return true; // 已比较过,视为相等(避免循环引用死循环)
        comparedObjects.Add(tuple);

        // 获取所有公共实例属性
        var properties = a.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
        foreach (var prop in properties)
        {
            // 跳过索引器属性
            if (prop.GetIndexParameters().Length > 0)
                continue;

            var valueA = prop.GetValue(a);
            var valueB = prop.GetValue(b);

            // 递归比较属性值
            if (!CheckEqual(valueA, valueB))
                return false;
        }

        return true;
    }
}

// 测试用类
public class ExampleClass
{
    public string PropertyA { get; set; }
    public string PropertyB { get; set; }
    public List<int> NestedList { get; set; }
}

// 调用示例
public class Program
{
    public static void Main()
    {
        var a = new ExampleClass()
        {
            PropertyA = "A",
            PropertyB = "B",
            NestedList = new List<int> { 1, 2, 3 }
        };

        var b = new ExampleClass()
        {
            PropertyA = "A",
            PropertyB = "B",
            NestedList = new List<int> { 1, 2, 3 }
        };

        var c = new ExampleClass()
        {
            PropertyA = "C",
            PropertyB = "B",
            NestedList = new List<int> { 1, 2 }
        };

        Console.WriteLine(ObjectComparer.CheckEqual(a, b)); // 输出 True
        Console.WriteLine(ObjectComparer.CheckEqual(a, c)); // 输出 False
    }
}

关键细节说明

  • null处理:先判断引用相等,再处理单null的情况
  • 类型校验:严格要求两个对象类型完全相同(子类和父类会被视为不同)
  • 值类型与字符串:直接使用Equals比较,避免反射开销
  • 集合支持:遍历集合元素逐个比较,确保元素数量和内容都一致
  • 循环引用防护:用HashSet记录已比较的对象对,防止无限递归
  • 索引器跳过:忽略带有索引参数的属性,避免不必要的复杂处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:25:13