我在for循环中对SequenceEqual和元素比较进行了比较。
static void Main(string[] args)
{
//var myList = new List<short>();
//var anotherList = new List<short>();
var myList = new short[2000000];
var anotherList = new short[2000000];
for (int i = 0; i < 2000000; i++)
{
//myList.Add(5);
//anotherList.Add(5);
myList[i] = 5;
anotherList[i] = 5;
}
var watch = System.Diagnostics.Stopwatch.StartNew();
//for (int i = 0; i < 2000000; i++)
//{
// if (myList[i] != anotherList[i])
// break;
//}
bool isEqual = myList.SequenceEqual(anotherList);
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine(elapsedMs);
Console.Read();
}
在myList和anotherList是数组的情况下,直接比较执行4 ms,SequenceEqual执行21ms。当myList和anotherList是列表时,直接比较执行13 ms,SequenceEqual执行30 ms。
如果速度慢得多,是否有使用它的情况?我只能想到一个,它可以保存几行代码。
答案 0 :(得分:1)
特别针对List
进行研究,似乎很慢的问题来自SequenceEqual
中使用通用IEnumerator
而非List
特定的通用实现版本,速度是原来的两倍多。但是,如果您要测试List
,也可以直接在for
循环中编码,而不是使用枚举。
请注意,对IList
的测试速度要慢得多,因为List
没有实现IList<T>.operator[]
,这意味着它会调用IList.operator[]
并返回object
并导致拳击。
我也是特殊情况Array
,因为IList
接口比直接访问慢得多,这也是因为拳击。
当然,利用已知类型的高速Count
或Length
,可以使得不等长度比较比SequenceEqual
快得多。 OTOH,如果前两个元素不相等,SequenceEqual
可能比我的函数更快。
这是我的LocalSequenceEqual
:
public static bool LocalSequenceEqual<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer = null) {
if (first is ICollection<TSource> fc && second is ICollection<TSource> sc)
if (fc.Count != sc.Count)
return false;
var cmp = comparer ?? EqualityComparer<TSource>.Default;
if (first is TSource[] fa && second is TSource[] sa) {
for (int j1 = 0; j1 < fa.Length; ++j1)
if (!cmp.Equals(fa[j1], sa[j1]))
return false;
return true;
}
if (first is List<TSource> fl && second is List<TSource> sl) {
for (int j1 = 0; j1 < fl.Count; ++j1) {
if (!cmp.Equals(fl[j1], sl[j1]))
return false;
}
return true;
}
using (var e1 = first.GetEnumerator()) {
using (var e2 = second.GetEnumerator()) {
while (e1.MoveNext()) {
if (!(e2.MoveNext() && cmp.Equals(e1.Current, e2.Current)))
return false;
}
if (e2.MoveNext())
return false;
}
}
return true;
}