【问题标题】:Collections with user defined class - find differences具有用户定义类的集合 - 查找差异
【发布时间】:2021-05-31 10:44:42
【问题描述】:

这是我的模型:

public class EventModel
{
    public DateTime? EVENT_DATE { get; set; }
    public decimal? EVENT_TYPE { get; set; }
    public string EVENT_DESCRIPTION { get; set; }
}

我将此课程填入ObservableCollection<EventModel>。当我这样做时,我也会深拷贝同一个集合。然后我想在以后的使用中比较这两个集合。

我最好使用 LINQ 来做到这一点,比如

bool are_same = collection1.OrderBy(i => i).SequenceEqual(
                 collection2.OrderBy(i => i));

这意味着需要对两个集合进行排序,然后相互比较以找出ALL PROPERTIES 中的差异。

有很多实现IComparable & IEqualityComparer 的示例,但我对我需要什么以及如何实现感到困惑。

如果有人能告诉我如何在 C# 中完成此操作,我将不胜感激。

【问题讨论】:

  • 具体显示什么?发现差异?如何实现 IComparable/IEqualityComparer?比较集合时顺序是否重要?输出应该是什么?你能举一个输入/预期输出的例子吗?这里的最终目标是什么?
  • @JonasH, collection1 是绑定到 UI 的集合。 collection2 用于启用按钮以保存对数据库的更改。所以输出应该是一个boolean,表示集合中的任何属性是否发生了变化。项目总是在同一个位置(我认为),我从数据库中获取数据后立即深复制collection1

标签: c# observablecollection iequalitycomparer icomparable


【解决方案1】:

如果您只是想检查两个集合是否相等,您需要定义什么是相等,例如通过实现IEqualityComparer<T>。这也可以通过实现IEquatable<T> 或覆盖Equals(object)GetHasCode 来完成。这可以通过一些重构工具自动完成:

public sealed class EventModelEqualityComparer : IEqualityComparer<EventModel>
    {
        public bool Equals(EventModel x, EventModel y)
        {
            if (ReferenceEquals(x, y)) return true;
            if (ReferenceEquals(x, null)) return false;
            if (ReferenceEquals(y, null)) return false;
            if (x.GetType() != y.GetType()) return false;
            return Nullable.Equals(x.EVENT_DATE, y.EVENT_DATE) &&
                   x.EVENT_TYPE == y.EVENT_TYPE &&
                   x.EVENT_DESCRIPTION == y.EVENT_DESCRIPTION;
        }

        public int GetHashCode(EventModel obj)
        {
            unchecked
            {
                var hashCode = obj.EVENT_DATE.GetHashCode();
                hashCode = (hashCode * 397) ^ obj.EVENT_TYPE.GetHashCode();
                hashCode = (hashCode * 397) ^ (obj.EVENT_DESCRIPTION != null ? obj.EVENT_DESCRIPTION.GetHashCode() : 0);
                return hashCode;
            }
        }
    }

要比较两个集合以查看它们是否包含相同的项目,但在任意位置,您可以使用HashSet.SetEquals

myCollection.ToHashSet(new EventModelEqualityComparer()).SetEquals(myOtherCollection);

【讨论】:

  • 如果我理解正确的话,这个类是完全独立的。我不应该直接在 EventModel 中实现 IEqualityCompared 吗?接下来,如何自动完成,您提到了重构工具?最后,如果进行了更改,这个返回布尔值吗?
  • IEqualityComparer 的实现是一个独立的类,但如果您愿意,也可以作为嵌套类实现。您可以让EventModel 实现IEquatable,这更容易使用,因为您不需要定义equalComparer,但不太灵活,因为您只能有一个IEquatable 实现。如果集合包含相同的项目,SetEquals 将返回 true,否则返回 false。
  • @lucy82 ToHashSet 应该为所有IEnumerable&lt;T&gt; 定义,包括 ObservableCollection,检查您是否导入了正确的命名空间并且使用的是 .Net 4.8 或更高版本。不知道在所有情况下都不工作是什么意思。当(且仅当)它们的所有属性都相等时,上面的比较代码应该认为两个对象相等。
  • @Lucy82 仅当对象更改顺序时,例如删除一个对象并添加另一个相同的对象。
  • @Auditive Except 只会检查collection1 中的所有项目是否存在于collection2 中,而不是相反,即使用集合表示法collection1 ⊆ collection2 而不是collection1 = collection2。请注意,您可以轻松添加扩展方法:ToHashSet(this IEnumerable&lt;T&gt; e) =&gt; new HashSet(e);
猜你喜欢
  • 1970-01-01
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
  • 2013-11-26
  • 1970-01-01
  • 2021-11-26
  • 1970-01-01
  • 2010-11-24
相关资源
最近更新 更多