如何编写处理两个包含任意类型对象的列表的泛型函数

本文关键字:对象 类型 列表 函数 泛型 包含任 两个 处理 何编写 | 更新日期: 2023-09-27 17:59:50

我想写一个函数来处理两个相同对象的List。该功能总是做同样的事情:

  1. 查找只在清单2中但不在清单1中的对象->对它们执行操作
  2. 找到两个列表中的对象->对它们执行不同的操作

现在的重点是,我有List对,它们包含不同类型的对象,我想对它们应用这个精确的过程。示例:

List<Foo1> L11, L12;
List<Foo2> L21, L22;
List<Foo3> L31, L32;

那么,我必须如何编写代码,这样我就不必为每个List类型重复代码了?

问候和感谢

如何编写处理两个包含任意类型对象的列表的泛型函数

我会准备一个方法,如下所示:

static void Process<T>(IEnumerable<T> list1, IEnumerable<T> list2, Action<T> onlyIn2, Action<T> inBoth)
{
    var hash = new HashSet<T>(list1);
    foreach (var item2 in list2)
        if (hash.Contains(item2))
            inBoth(item2);
        else
            onlyIn2(item2);
}

然后您可以按如下方式使用它:

var list1 = new List<int> {1, 2, 3, 4, 5};
var list2 = new List<int> {3, 4, 5, 6};
Process(list1, list2, a =>
{
    Console.WriteLine("{0} only in 2", a);
}, a =>
{
    Console.WriteLine("{0} in both", a);
});

请注意,它使用标准比较规则(对于对象引用相等,除非覆盖了Equals或实现了IEqualityComparer<TKey>)。

LINQ已经提供了两种实现这一点的方法:

// get all members of L11 not present in L12
var except = L11.Except(L12).ToList();
// get members present in both lists
var intersect = L11.Intersect(L12).ToList();

这些重载将使用列表元素类型的默认比较器,因此由于要比较自定义类,因此需要使用接受自定义IEqualityComparer<T>:的重载

var comparer = new CustomComparer();
var except = L11.Except(L12, comparer).ToList();
var intersect = L11.Intersect(L12, comparer).ToList();

你需要自己写:

class CustomComparer : IEqualityComparer<SomeClass>
{
    public bool Equals(SomeClass x, SomeClass y)
    {
        // return true if equal
    }
    public int GetHashCode(SomeClass obj)
    {
        // return a hash code for boj
    }
}

您可以使用Except/Insectt-Linq方法,如下所示:

void Process<T>(IList<T> list1, IList<T> list2, IEqualityComparer<T> comparer = null) {
    //Find the objects that are only in List2 but not in List1 
    foreach(var item in list2.Except(list1, comparer)) {
        // -> Do something with them
    }
    //Find the object that are in both Lists -> Do something different with them.
    foreach(var item in list1.Intersect(list2, comparer)) {
        // -> Do something different with them.
    }
}