【问题标题】:Why is there a separate equals method for sets?为什么集合有单独的 equals 方法?
【发布时间】:2013-06-20 14:01:02
【问题描述】:

在 C Sharp .NET 中有一个 Equals 方法和一个 SetEquals 方法。区别在哪里?

来自 Java,我的第一个想法是 SetEquals 不是必需的,只需对所有对象使用 Equals 方法即可。

【问题讨论】:

标签: c# equals


【解决方案1】:

SetEquals 不遵守与Equals 相同的合同。特别是它不是对称的,因为参数只是IEnumerable<T> 而不是ISet<T>。这允许您在仅设置 one 时检查设置是否相等。考虑:

List<int> intList = new List<int> { 1, 2, 3 };
HashSet<int> intSet = new HashSet<int>(intList);

现在我们可以使用:

Console.WriteLine(intSet.SetEquals(intList));

...但是如果不对List&lt;int&gt; 和所有其他IEnumerable&lt;T&gt; 实现强制执行相同的行为,我们就无法以相同的方式实现Equals

即使我们将其限制在其他集合中,也存在一个有趣的问题,即平等的真正含义。例如,考虑两个 HashSet&lt;string&gt; 集合,它们包含相同的字符串,但具有不同的相等比较器。 (也许一个区分大小写,一个不区分。)它们是否相等? SetEquals 通过避免过于笼统来设法避免此类哲学问题。

HashSet&lt;int&gt;SortedSet&lt;int&gt; 怎么样?他们能平等吗?它们可以具有相同的值 - 但一个的顺序是不确定的。

总的来说,Object.EqualsObject.GetHashCode 的想法在我看来太宽泛了。通常你想要一个特定的type 相等 - 而且通常首先比较对象是否相等是没有意义的。这很容易成为一个完全不同的咆哮的主题,但与此同时,我至少很高兴 .NET 没有尝试将这个过于宽泛的想法应用于集合。 IMO,使用具有明确含义的SetEquals 的能力更有用。

【讨论】:

    【解决方案2】:

    HashSet&lt;T&gt;.SetEquals 确定 HashSet 是否包含与给定 IEnumerable&lt;T&gt; 相同的元素。但是如果类型不同,为什么要返回true呢?

    HashSet<int> h = new HashSet<int>();
    h.Add(0);
    h.Add(1);
    int[] ints = new[] { 0, 1, 1, 0 };
    h.SetEquals(ints); // true, ignores duplicates because it's a set
    h.Equals(ints); // false, correct because not even the same types
    

    MSDN:

    SetEquals 方法忽略重复条目和顺序 其他参数中的元素.....

    由于HasetSet&lt;T&gt; 没有覆盖Equals,它使用从仅比较引用的对象继承的对象。因此,如果两个对象不是同一个引用,则返回 false

    【讨论】:

      【解决方案3】:
      • Equals 将测试两个 HashSets 是否是同一个对象。
      • SetEquals 接受IEnumerable&lt;T&gt;,它的作用是:“SetEquals 方法会忽略另一个参数中的重复条目和元素顺序。”

      所以SetEquals 用于测试您是否将 IEnumerable 加载到 HashSet 中,它是否会生成与源相同的 HashSet。

      【讨论】:

        【解决方案4】:

        Equals 检查两者之间的引用是否相等,SetEquals 将检查集合中的元素。

        【讨论】:

          【解决方案5】:

          SetEquals:

          检查 HashSet 是否包含与给定 IEnumerable&lt;T&gt; 相同的元素。

          SetEquals 方法将第二个集合视为没有重复元素。如果存在重复元素,则两个集合仍可能被视为相等。

          等于:

          Equals 实际上是一个参照测试

          List<string> stringList = new List<string> { "a", "b", "c" };
          SortedSet<string> stringSet = new SortedSet<string> { "a", "b", "c" };
          
          bool a = stringSet.SetEquals(stringList );
          // See if the two collections contain the same elements.
          

          【讨论】:

            【解决方案6】:
            public static void Main(string[] args)
                    {
                        Console.WriteLine("Hello World!");
            
                        System.Collections.Generic.HashSet<int> setA= new System.Collections.Generic.HashSet<int>();
                        setA.Add(1);
                        System.Collections.Generic.HashSet<int> setB= new System.Collections.Generic.HashSet<int>();
                        setB.Add(1);
            
            
                        Console.WriteLine("Equals method returns {0}", setA.Equals(setB));
                        Console.WriteLine("SetEquals method returns {0}", setA.SetEquals(setB));
            
            
                        Console.Write("Press any key to continue . . . ");
                        Console.ReadKey(true);
                    }
            

            产生输出: Equals 方法返回 False SetEquals 方法返回 True

            因此,equals 方法似乎是对引用相等性的测试。

            【讨论】:

              【解决方案7】:

              ISet&lt;T&gt;.SetEquals 实现

              判断当前集合和指定集合是否包含相同的元素。

              继承自objectEquals实现

              相当于调用 ReferenceEquals 方法。

              继承的ReferenceEquals实现,

              判断指定的Object实例是否为同一个实例。


              特别注意,传递给SetEqualsIEnumerable&lt;T&gt; 序列可以以任意顺序包含集合中每个成员的一个或多个实例,而SetEquals 仍将返回true。


              如果您想确认两个序列是否包含以相同顺序完全相同的成员,您可以使用SequenceEqual 扩展。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-11-13
                • 1970-01-01
                • 2011-03-24
                • 2023-03-08
                相关资源
                最近更新 更多