What is the best way to check two List <T> lists for equality in C #

There are many ways to do this, but I feel like I am missing out on some function or something like that.

Obviously, List == List will use Object.Equals() and return false .

If each element of the list is equal and is present in the same place in the opposite list, I would consider them equal. I use value types, but a correctly implemented Data object should work the same way (I am not looking for a small copied list, only that the value of each object inside is the same).

I tried searching and there are similar questions, but my question is the equality of each element in the exact order.

+18
equality list c # linq
May 18 '09 at 6:54 a.m.
source share
6 answers
 Enumerable.SequenceEqual<TSource> 

MSDN

+39
May 18 '09 at 6:58 a.m.
source share

Realization of evil

 if (List1.Count == List2.Count) { for(int i = 0; i < List1.Count; i++) { if(List1[i] != List2[i]) { return false; } } return true; } return false; 
+3
May 18 '09 at 6:59 a.m.
source share

I collected this variation:

 private bool AreEqual<T>(List<T> x, List<T> y) { // same list or both are null if (x == y) { return true; } // one is null (but not the other) if (x== null || y == null) { return false; } // count differs; they are not equal if (x.Count != y.Count) { return false; } for (int i = 0; i < x.Count; i++) { if (!x[i].Equals(y[i])) { return false; } } return true; } 

The nerd in me also scanned, so I ran a performance test with SequenceEquals, and this has a slight advantage.

Now ask a question; Is this a tiny, almost measurable performance gain that is worth adding code to the code base and maintaining it? I highly doubt it: o)

+3
May 18 '09 at 7:14
source share

I knocked out a quick extension method:

 namespace ExtensionMethods { public static class MyExtensions { public static bool Matches<T>(this List<T> list1, List<T> list2) { if (list1.Count != list2.Count) return false; for (var i = 0; i < list1.Count; i++) { if (list1[i] != list2[i]) return false; } return true; } } } 
+2
May 18 '09 at 7:03 a.m.
source share

You can write the general sequence IEqualityComparer<T> for sequences. Plain:

 public class SequenceEqualityComparer<T> : IEqualityComparer<IEnumerable<T>> { public bool Equals(IEnumerable<T> x, IEnumerable<T> y) { return x.SequenceEqual(y); } public int GetHashCode(IEnumerable<T> obj) { return unchecked(obj.Aggregate(397, (x, y) => x * 31 + y.GetHashCode())); } } 



More complicated version : it should be better.

 public class SequenceEqualityComparer<T> : EqualityComparer<IEnumerable<T>>, IEquatable<SequenceEqualityComparer<T>> { readonly IEqualityComparer<T> comparer; public SequenceEqualityComparer(IEqualityComparer<T> comparer = null) { this.comparer = comparer ?? EqualityComparer<T>.Default; } public override bool Equals(IEnumerable<T> x, IEnumerable<T> y) { // safer to use ReferenceEquals as == could be overridden if (ReferenceEquals(x, y)) return true; if (x == null || y == null) return false; var xICollection = x as ICollection<T>; if (xICollection != null) { var yICollection = y as ICollection<T>; if (yICollection != null) { if (xICollection.Count != yICollection.Count) return false; var xIList = x as IList<T>; if (xIList != null) { var yIList = y as IList<T>; if (yIList != null) { // optimization - loops from bottom for (int i = xIList.Count - 1; i >= 0; i--) if (!comparer.Equals(xIList[i], yIList[i])) return false; return true; } } } } return x.SequenceEqual(y, comparer); } public override int GetHashCode(IEnumerable<T> sequence) { unchecked { int hash = 397; foreach (var item in sequence) hash = hash * 31 + comparer.GetHashCode(item); return hash; } } public bool Equals(SequenceEqualityComparer<T> other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return this.comparer.Equals(other.comparer); } public override bool Equals(object obj) { return Equals(obj as SequenceEqualityComparer<T>); } public override int GetHashCode() { return comparer.GetHashCode(); } } 

This has several features:

  • Comparison is performed from bottom to top. In typical use cases, it is highly likely that collections will differ at the end.

  • And IEqualityComparer<T> can be passed to base comparisons on items in the collection.

+1
Jun 30 '15 at 1:39
source share

Use linq SequenceEqual to check sequence equality, because the Equals method checks reference equality.

 bool isEqual = list1.SequenceEqual(list2); 

The SequenceEqual() method takes a second sequence, I Enumerable<T> as a parameter, and performs a comparison on the elements with the target (first) sequence. If two sequences contain the same number of elements, and each element in the first sequence is equal to the corresponding element in the second sequence (using the default comparison), then SequenceEqual() returns true . Otherwise, false returned.

Or, if you do not need the order of the elements, use the Enumerable.All method:

 var isEqual = list1.All(list2.Contains); 

The second version also requires a different check for Count, because it will return true, even if list2 contains more elements than list1 .

0
Nov 12 '17 at 9:35 on
source share



All Articles