为什么集合有单独的equals方法?

时间:2013-06-20 14:01:02

标签: c# equals

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

来自Java,我首先想到的是SetEquals不是必需的,只需对所有对象使用Equals方法。

7 个答案:

答案 0 :(得分:33)

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

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

现在我们可以使用:

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

...但如果不对Equals和其他List<int>实施执行相同的行为,我们就无法以相同的方式实施IEnumerable<T>

即使我们将其限制在其他集合中,也存在一个有趣的问题,即平等究竟意味着什么。例如,考虑两个HashSet<string>集合,它们包含相同的字符串,但具有不同的相等比较器。 (也许一个是区分大小写的,一个不是。)这些是否相等? SetEquals设法通过避免过于笼统来避免这些哲学问题。

HashSet<int>SortedSet<int>怎么样?他们能平等吗?它们可以具有相同的值 - 但是一个的排序是未定义的。

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

答案 1 :(得分:11)

HashSet<T>.SetEquals确定HashSet是否包含与给定IEnumerable<T>相同的元素。但是,如果类型不同,为什么它会返回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<T>不覆盖Equals,因此它使用从对象继承的那个,它只是比较引用。因此,如果两个对象不是同一个引用,则返回false

答案 2 :(得分:5)

  • Equals会测试两个HashSet是否是同一个对象。
  • SetEquals接收IEnumerable<T>,它的作用是:“SetEquals方法忽略重复的条目以及其他参数中元素的顺序。”

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

答案 3 :(得分:3)

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

答案 4 :(得分:0)

SetEquals:

  

检查HashSet是否包含与给定 IEnumerable <T> 相同的元素。

     

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.

答案 5 :(得分:0)

ISet<T>.SetEquals实施

  

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

object

继承的Equals实施
  

相当于对ReferenceEquals方法的调用。

继承的ReferenceEquals实施,

  

确定指定的Object实例是否是同一个实例。


请注意,传递给IEnumerable<T>的{​​{1}}序列可以按任意顺序包含该集合中每个成员的一个或多个实例,SetEquals仍然会返回true。


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

答案 6 :(得分:0)

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方法似乎是对参照平等的测试。