To compare two sequences using except, you'll need to check both directions. For example:
List<T> a, b;
IEqualityComparer<T> cmp = ...
var areEqual = !a.Except(b, cmp).Concat(b.Except(c, cmp)).Any();
This issue comes up twice in your code: first when you are comparing 2 lists of slides and again when you are comparing 2 lists of charts.
Another thing to be aware of when using Except()
for collection comparison is that it acts as a set operation. Thus, { A, A, A }.Except({ A })
will return empty.
Thus, I'd recommend something more like the following:
public static bool CollectionEquals<T>(this ICollection<T> @this, ICollection<T> that, IEqualityComparer<T> cmp = null)
{
// to be equal, the 2 collections must not be null unless they're both null or have the same count
if (ReferenceEquals(@this, that)) { return true; }
if (@this == null || that == null) { return false; }
if (@this.Count != that.Count) { return false; }
// use the default comparer if one wasn't passed in
var comparer = cmp ?? EqualityComparer<T>.Default;
// to handle duplicates, we convert @this into a "bag" (a mapping
// from value -> # occurrences of that value in the collection
var thisDict = @this.GroupBy(t => t, comparer)
.ToDictionary(g => g.Key, g => g.Count(), comparer);
// do the same for that
var thatDict = @this.GroupBy(t => t, comparer)
.ToDictionary(g => g.Key, g => g.Count(), comparer);
// the two collections are equal if they have the same number of distinct values
return thisDict.Count == thatDict.Count
// and if, for each distinct value in @this, that value is also in that
// and has the same number of occurrences in @this and that
&& thisDict.All(kvp => thatDict.ContainsKey(kvp.Key)
&& thatDict[kvp.Key] == kvp.Value);
}