我想写一个函数来处理两个相同对象的List。该功能总是做同样的事情:
- 查找只在清单2中但不在清单1中的对象->对它们执行操作
- 找到两个列表中的对象->对它们执行不同的操作
现在的重点是,我有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.
}
}