我有一个项目对象:
class Item : IEquatable<Item>
{
public string Id { get; }
public string Name { get; }
public override bool Equals(object obj)
{
return Equals(obj as Item);
}
public bool Equals(Item other)
{
return other != null && Id == other.Id;
}
public override int GetHashCode()
{
return 2108858624 + Id.GetHashCode();
}
}
做交集:
Item[] items1 = new Item[] { new Item() { Id = 1, Name = 1 } };
Item[] items2 = new Item[] { new Item() { Id = 1, Name = 2 } };
IEnumerable<Item> intersection = items1.Intersect(items2).ToList();
它表明它选择Name = 1
项目。
我的问题是保证Intersect
始终从第一个可枚举而不是第二个中选择项目?我找不到有关Intersect
确切选择的实例的任何信息。
我知道由于两个项目相同,我不需要知道Intersect
选择了哪个实例。但这是我的情景:
想象一下这样一种场景,即本地应用程序中存储了项目,并且需要将这些项目与来自后端的项目合并。具有相同ID的在线项目可能会更新Name
,但它仍然是#34;相同的项目&#34;与本地存储的项目。这就是了解Intersect
选择哪个实例的重要原因。
所以也许我的问题出在其他地方?
.NET允许我们覆盖&#34;平等&#34;两个对象之间的意思。但是,当使用Intersect
和其他LINQ时,对我来说似乎有点模糊。
答案 0 :(得分:2)
您可以查看source code:
public static IEnumerable<TSource> Intersect<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second) {
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return IntersectIterator<TSource>(first, second, null);
}
public static IEnumerable<TSource> Intersect<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
if (first == null) throw Error.ArgumentNull("first");
if (second == null) throw Error.ArgumentNull("second");
return IntersectIterator<TSource>(first, second, comparer);
}
static IEnumerable<TSource> IntersectIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
Set<TSource> set = new Set<TSource>(comparer);
foreach (TSource element in second) set.Add(element);
foreach (TSource element in first)
if (set.Remove(element)) yield return element;
}
如您所见,它返回第一组中与第二组中的元素匹配的元素。
然而,正如蒂姆正确地写的那样 - 源代码不是具有约束力的合同。在将来的版本中,此行为可能会发生变化,因此最好不要依赖源代码作为保证。
请注意,Enumerable.Intersect
方法Microsoft Docs页面的备注部分也记录了它:
两组A和B的交集定义为包含 A 的所有元素的集合,它们也出现在B中,但没有其他元素。
(强调我的)
答案 1 :(得分:2)
Zohar已经回答的问题有点偏离主题。但OP在评论中说:
假设我想知道哪些本地商品 与从后端收到的项目相同。我现在的结论是
Intersect
无法帮助我解决这个问题。我想知道哪些项目改变了所以我 可以更新本地版本。我不能用它来覆盖本地的 从后端获取的,因为有一些合并逻辑需要 发生,否则我可以覆盖已更改的本地 本地
嗯,这与你在问题中提到的要求不同(合并并从一个来源获取),而Intersect
确实没有多大帮助。
var changedNameItems = from l in localItems
join o in onlineItems
on l.Id equals o.Id
where l.Name != o.Name
select new{ LocalItem = l, OnlineItem = o };
foreach(var x in changedNameItems)
{
// if you want to change the local item's name:
x.LocalItem.Name = x.OnlineItem.Name;
}