代码之家  ›  专栏  ›  技术社区  ›  Don Box

从intersect返回哪个项,从第一个可枚举项还是从第二个可枚举项返回?

  •  1
  • Don Box  · 技术社区  · 7 年前

    我有一个项目对象:

    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 总是从第一个可枚举项而不是第二个可枚举项中选择项?我找不到任何关于哪个实例的信息 横断 完全可以选择。

    我知道既然两项是相等的,我就不需要知道哪个实例是由 横断 . 但我的设想是:

    想象一下这样一个场景:应用程序中有本地存储的项,它们需要与来自后端的项合并。具有相同ID的联机项目可能具有 Name 已更新,但仍与本地存储的项“相同”。这就是为什么了解哪个实例 横断 选择。

    也许我的问题出在别的地方?

    .NET允许我们重写两个对象之间的“相等”含义。但是,当使用 横断 还有其他林肯的东西,我觉得有些模糊。

    2 回复  |  直到 7 年前
        1
  •  2
  •   Tim Schmelter    7 年前

    有点离题 Zohar 已经回答了。但op在评论中说:

    假设我想知道哪些是本地商品 从后端接收的项目也是如此。我现在的结论是 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;
    }
    
        2
  •  2
  •   Zohar Peled    7 年前

    你可以看看 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;
        }
    

    如您所见,它返回第一个集合中与第二个集合中的元素匹配的元素。

    然而,正如tim正确地写的那样-源代码不是一个绑定契约。这种行为在将来的版本中可能会发生变化,因此最好不要依赖源代码作为保证。

    请注意,它也记录在 Enumerable.Intersect 方法Microsoft文档页:

    两个集合A和B的交集定义为包含 所有的元素 也出现在b中,但没有其他元素。

    (强调我的)