There wasn't, isn't and might not be, at least I would believe so. The reason behind is collection equality is probably an user defined behavior.
Elements in collections are not supposed to be in a particular order though they do have an ordering naturally, it's not what the comparing algorithms should rely on. Say you have two collections of:
{1, 2, 3, 4}
{4, 3, 2, 1}
Are they equal or not? You must know but I don't know what's your point of view.
Collections are conceptually unordered by default, until the algorithms provide the sorting rules. The same thing SQL server will bring to your attention is when you trying to do pagination, it requires you to provide sorting rules:
https://learn.microsoft.com/en-US/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-2017
Yet another two collections:
{1, 2, 3, 4}
{1, 1, 1, 2, 2, 3, 4}
Again, are they equal or not? You tell me ..
Element repeatability of a collection plays its role in different scenarios and some collections like Dictionary<TKey, TValue>
don't even allow repeated elements.
I believe these kinds of equality are application defined and the framework therefore did not provide all of the possible implementations.
Well, in general cases Enumerable.SequenceEqual
is good enough but it returns false in the following case:
var a = new Dictionary<String, int> { { "2", 2 }, { "1", 1 }, };
var b = new Dictionary<String, int> { { "1", 1 }, { "2", 2 }, };
Debug.Print("{0}", a.SequenceEqual(b)); // false
I read some answers to questions like this(you may google for them) and what I would use, in general:
public static class CollectionExtensions {
public static bool Represents<T>(this IEnumerable<T> first, IEnumerable<T> second) {
if(object.ReferenceEquals(first, second)) {
return true;
}
if(first is IOrderedEnumerable<T> && second is IOrderedEnumerable<T>) {
return Enumerable.SequenceEqual(first, second);
}
if(first is ICollection<T> && second is ICollection<T>) {
if(first.Count()!=second.Count()) {
return false;
}
}
first=first.OrderBy(x => x.GetHashCode());
second=second.OrderBy(x => x.GetHashCode());
return CollectionExtensions.Represents(first, second);
}
}
That means one collection represents the other in their elements including repeated times without taking the original ordering into account. Some notes of the implementation:
GetHashCode()
is just for the ordering not for equality; I think it's enough in this case
Count()
will not really enumerates the collection and directly fall into the property implementation of ICollection<T>.Count
If the references are equal, it's just Boris
Enumerable.SequenceEqual
andISet.SetEquals
provide versions of this functionality. If you want to be order-agnostic and work with collections that have duplicates, you'll need to roll your own. Check out the implementation suggested in this post – NarcoCollectionAssert.AreEquivalent
. – Misery