Kathy's approach seems a good one to me. I'd personally allow the comparer to be specified explicitly:
bool AreEqual<T>(T[] a, T[] b){
return AreEqual(a, b, EqualityComparer<T>.Default);
}
bool AreEqual<T>(T[] a, T[] b, IEqualityComparer<T> comparer){
if(a.Length != b.Length)
return false;
for(int i = 0; i < a.Length; i++)
if(comparer.Equals(a[i], b[i])
return false;
return true;
}
SequenceEqual as mentioned by CMS is good, but due to its generality over IEnumerable<T>
I don't think it can do the "early out" if the length aren't equal. (It's possible that it checks for both sequences implementing IList though, to check Count directly.) You could generalise a little more, to use IList<T>
bool AreEqual<T>(IList<T> a, IList<T> b, IEqualityComparer<T> comparer){
if(a.Count != b.Count)
return false;
for(int i = 0; i < a.Count; i++)
if(comparer.Equals(a[i], b[i])
return false;
return true;
}
The straight array version will probably be the most efficient - adding generality and abstraction usually hits performance, although whether it's significant will depend on your app.