如果您的employees 和contacts 序列是相同类型的对象(或者都继承自相同类型,例如Contact),那么您可以创建一个EqualityComparer 实例:
public class ContactComparer : EqualityComparer<Contact>
{
public override bool Equals(Contact x, Contact y)
{
if (ReferenceEquals(x, y)) return true;
return x != null && y != null && x.ContactId == y.ContactId;
}
public override int GetHashCode(Contact obj)
{
if (obj == null) throw new ArgumentNullException("obj");
// assuming string
return (obj.ContactId ?? "").GetHashCode();
}
}
这会让你这样做,因此你可以直接返回结果而不必重复查询:
var contactsNotEmployees = myContacts.Except(employees, new ContactComparer()).ToList();
更新:正如您的评论所示,Contact 和 Employee 是不同的类型,您可以考虑使用 ContactId 属性创建一个接口来创建一个共同的纽带。
或者,我建议将您的 except 结果导出到 HashSet,然后使用 HashSet 中的 Contains(),这是 O(1) 效率(而不是序列上的 Contains(),即O(n) 效率):
// get hash set of contact-only IDs
var except = new HashSet<int>(contacts
.Select(c => c.ContactId)
.Except(emplopyees.Select(e => e.ContactId)));
// get the objects for those IDs
var others = contacts.Where(c => except.Contains(c.ContactId)).ToList();
比较使用序列 Contains() 和 HashSet Contains() 的结果,对于小列表(15 项),您的速度大约快 50%,对于较长的列表甚至更快。
不管怎样,把它扔掉,因为序列 (IEnumerable<T>) 上的 Contains() 相对较慢...
我对这两个解决方案进行了超过 1,000,000 次迭代,并得到:
HashSet With Contains() took: 1429 ms, 0.001429 ms/item.
Sequence With Contains() took: 3386 ms, 0.003386 ms/item.