为什么我的 List.Intersect 返回的结果与 Where(List.Contains) 不同的结果
本文关键字:List 结果 Contains Where 返回 我的 为什么 Intersect | 更新日期: 2023-09-27 18:36:52
我正在处理一个Active Directory同步项目,我正在尝试将AD中的用户列表与存储在数据库中的用户列表进行比较。我实现了一个自定义UserPrincipal
(我创造性地称之为NetworkUserPrincipal
),以公开我们在入职期间需要设置的一些属性。 NetworkUserPrincipal
还实现了IEqualityComparer<NetworkUserPrincipal>
。
我还在研究小样本量的单元测试,我正在尝试制定一个过程来跳过信息未更改的每个人。这是我的测试:
// a static list of two users
List<NetworkUserPrincipal> expected = JobTestData.InternalActiveDirectoryData.SynchronizedUsers
// returns only one user.
List<NetworkUserPrincipal> actual = _activeDirectoryUsers.Intersect(_databaseUsers).ToList(); // returns only one user.
Assert.IsTrue(expected.All(_databaseUsers.Contains)); // true
Assert.IsTrue(expected.All(_activeDirectoryUsers.Contains)); // true
Assert.IsTrue(expected.SequenceEqual(actual)); // false
但是,如果我将_activeDirectoryUsers.Intersect(_databaseUsers).ToList();
更改为_activeDirectoryUsers.Where(_databaseUsers.Contains).ToList();
,我的最终测试就会通过。
当我调试单元测试时,我在 Equals 覆盖函数中放置了一个断点,并且在Intersect
方案中只调用一次。
这是怎么回事?
正确的GetHashCode()
实现才能使用Intersect
。不知道为什么,但没有它确实有问题。
没有 GetHashCode() 的小提琴
摆弄 GetHashCode()
似乎GetHashCode
的任何实现(即使是不正确的实现)都可以,只是不是默认的对象。
编辑:正如@ScottChamberlain注释中所解释的那样,不是任何不正确的实现都可以工作,它确实需要一个正确的实现(其中每个相等的对象返回一个相等的哈希码)。它不需要高效,只需正确即可。
SequenceEqual
要求两个列表具有相同的内容和相同的顺序。问题是顺序不同。改用CollectionAssert.AreEquivalent
,它不关心集合的顺序。
CollectionAssert.AreEquivalent(expected,actual);
此外,Intersect
确实对结果执行隐式Distinct()
。 如果您有两个相同的项目,expected.All(_databaseUsers.Contains)
会通过,但两个列表可能具有不同的计数。