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

如何比较两个不同复杂类型的列表?解决多属性匹配及报错问题

不同复杂类型列表的属性批量比较方案

场景与需求

现有两个不同复杂类型的C#列表,需要比较两个列表中对应元素的所有属性,获取每个属性的匹配结果(true或false)。由于列表对应的类包含100+属性,需要一种可扩展、无需逐个编写比较逻辑的方案。

示例代码

列表初始化

List<Test> t1 = new List<Test>()
{
    new Test("TestName", "MyProperty", 50), 
    new Test("TestName2", "MyProperty2", 50)               
};
 
List<Test2> t2 = new List<Test2>()
{
    new Test2
    {
        NameT2 = "TestName",
        PropertyT2 = "MyProperty",
        ValueT3 = 50
    },
    new Test2
    {  
        NameT2 = "Hector",
        PropertyT2 = "MyProperties",
        ValueT3 = 60
    }    
};

类定义

public class Test
{
    public Test(string name, string property, int value)
    {
        Name = name;
        Property = property;
        Value = value;
    }

    public string Name { get; set; }
    public string Property { get; set; }
    public int Value { get; set; }
}

public class Test2
{
    public string NameT2 { get; set; }
    public string PropertyT2 { get; set; }
    public int ValueT3 { get; set; }
    public int AdditionalT4 { get; set; }
}

遇到的问题

之前尝试的两种方案均存在缺陷:

  • 手动编写Linq比较逻辑:由于属性数量超过100个,逐个编写比较代码工作量极大,且后续属性变更时维护成本高。
  • 自定义DynamicComparer结合Intersect:因两个类的属性名不匹配(如Test的Name对应Test2的NameT2),运行时抛出异常:'IdaTransaction.POC.DotNetApps.Model.DataModel.Test2' 不包含 'Name' 的定义。该Comparer代码如下:
public class DynamicComparer : IEqualityComparer<object>
{
    public bool Equals(dynamic x, dynamic y)
    {
        return x.Name == y.Name && x.Age == y.Age;
    }

    public int GetHashCode(dynamic obj)
    {
        return ((string)obj.Name).GetHashCode() * 31
            + ((int)obj.Age).GetHashCode();
    }
}

可行解决方案

通过反射+属性映射的方式实现动态批量比较,具体步骤如下:

1. 定义属性映射关系

创建字典存储两个类的属性对应关系,解决属性名不一致的问题:

var propertyMap = new Dictionary<string, string>
{
    { nameof(Test.Name), nameof(Test2.NameT2) },
    { nameof(Test.Property), nameof(Test2.PropertyT2) },
    { nameof(Test.Value), nameof(Test2.ValueT3) }
};

2. 封装通用比较方法

利用反射动态获取属性并比较值,返回每个属性的匹配结果列表:

using System.Reflection;

public static Dictionary<string, List<bool>> CompareLists<T1, T2>(List<T1> list1, List<T2> list2, Dictionary<string, string> propertyMapping)
{
    var comparisonResults = new Dictionary<string, List<bool>>();
    Type type1 = typeof(T1);
    Type type2 = typeof(T2);

    // 获取T1的所有公共实例属性
    PropertyInfo[] properties1 = type1.GetProperties(BindingFlags.Public | BindingFlags.Instance);

    foreach (PropertyInfo prop1 in properties1)
    {
        // 查找T2中对应的属性名
        if (propertyMapping.TryGetValue(prop1.Name, out string prop2Name))
        {
            PropertyInfo? prop2 = type2.GetProperty(prop2Name, BindingFlags.Public | BindingFlags.Instance);
            if (prop2 == null) continue;

            List<bool> propertyMatchResults = new List<bool>();
            int maxIndex = Math.Min(list1.Count, list2.Count);

            // 遍历两个列表的对应元素,比较属性值
            for (int i = 0; i < maxIndex; i++)
            {
                object? value1 = prop1.GetValue(list1[i]);
                object? value2 = prop2.GetValue(list2[i]);

                // 处理null值的比较
                bool isEqual = value1 == null ? value2 == null : value1.Equals(value2);
                propertyMatchResults.Add(isEqual);
            }

            comparisonResults.Add(prop1.Name, propertyMatchResults);
        }
    }

    return comparisonResults;
}

3. 使用示例

调用比较方法并输出结果:

var result = CompareLists(t1, t2, propertyMap);

// 打印每个属性的匹配结果
foreach (var kvp in result)
{
    Console.WriteLine($"属性 {kvp.Key} 的匹配结果:");
    foreach (bool match in kvp.Value)
    {
        Console.WriteLine($"\t{match}");
    }
}

方案优势

  • 适配大量属性:无需逐个编写比较逻辑,只需维护属性映射字典即可。
  • 灵活扩展:新增或修改属性时,仅需更新映射字典,无需修改核心比较逻辑。
  • 处理属性名差异:通过映射字典解决不同类之间属性名不匹配的问题。
  • 空值兼容:自动处理属性值为null的情况,避免空引用异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 00:57:29