如何编写通用函数处理两个列表持有任何类型的对象?

时间:2016-08-03 09:49:11

标签: c#

我想编写一个处理两个相同对象列表的函数。该功能总是一样的:

  1. 查找仅在List2中但不在List1中的对象 - >与他们做点什么
  2. 找到两个列表中的对象 - >做些与他们不同的事情。
  3. 现在重点是,我有List对,持有不同类型的对象,我想要应用这个精确的过程。 例如:

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

    那么我该如何编写代码,以便我不必为每个List类型重复代码?

    问候,谢谢

3 个答案:

答案 0 :(得分:1)

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

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>)。

答案 1 :(得分:1)

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
    }
}

答案 2 :(得分:1)

您可以使用Except / Intersect 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.
    }
}