В C Sharp.NET существует метод Equals
и метод SetEquals
. Где разница?
Начиная с Java, моя первая мысль заключалась в том, что SetEquals
не требуется, просто используйте метод Equals
для всех объектов.
В C Sharp.NET существует метод Equals
и метод SetEquals
. Где разница?
Начиная с Java, моя первая мысль заключалась в том, что SetEquals
не требуется, просто используйте метод Equals
для всех объектов.
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>
и a SortedSet<int>
? Могут ли они когда-либо быть равными? Они могут иметь одинаковые значения, но порядок одного составляет undefined.
В целом идеи Object.Equals
и Object.GetHashCode
слишком широки, на мой взгляд. Часто вам нужен определенный тип равенства - и часто нет смысла сравнивать объекты на равенство в первую очередь. Это может легко стать предметом совершенно другого разговора, но тем не менее я, по крайней мере, рад, что .NET не пыталась применить эту слишком широкую идею к коллекциям. Способность использовать SetEquals
с четко определенным значением более полезна, ИМО.
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 a set
h.Equals(ints); // false, correct because not even the same types
MSDN:
Метод SetEquals игнорирует повторяющиеся записи и порядок элементов в другом параметре.....
Так как HasetSet<T>
не переопределяет Equals
, он использует объект, унаследованный от объекта, который просто сравнивает ссылки. Поэтому, если два объекта не являются одной и той же ссылкой, он возвращает false
.
Equals
будет проверять, являются ли два HashSet
одним и тем же объектом.SetEquals
принимает IEnumerable<T>
, что он делает: "Метод SetEquals игнорирует повторяющиеся записи и порядок элементов в другой параметр".Итак, SetEquals
предназначен для тестирования, чтобы увидеть, загружен ли IEnumerable в HashSet, генерирует ли он тот же HashSet, что и ваш источник.
Equals
проверяет ссылочное равенство между двумя и SetEquals
будет проверять элементы в коллекции.
SetEquals:
Проверяет, содержит ли HashSet те же элементы, что и указанный IEnumerable
<T>
.Метод SetEquals рассматривает второй сборник, как будто он не имеет повторяющихся элементов. Если присутствуют повторяющиеся элементы, две коллекции могут по-прежнему считаться равными.
Равно:
Равные значения фактически являются ссылочным тестом
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.
ISet<T>.SetEquals
реализация
Определяет, содержат ли текущий набор и указанный набор те же элементы.
Equals
реализация, унаследованная от object
эквивалентен вызову метода ReferenceEquals.
Унаследованная ReferenceEquals реализация,
Определяет, являются ли указанные экземпляры объекта одним и тем же экземпляром.
В paticular обратите внимание, что последовательность IEnumerable<T>
, переданная в SetEquals
, может иметь один или несколько экземпляров каждого члена набора в любом порядке, а SetEquals
все равно вернет true.
Если вы хотите подтвердить, что две последовательности содержат точно такие же элементы в том же порядке, вы можете использовать расширение SequenceEqual
.
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 является испытанием на ссылочное равенство.