有兴趣,做法有什么不同吗?
所以,我创建了两个片段。
Snippet A
List<int> a = new List<int>();
a.Add(4);
a.Add(6);
int b = a.First();
and
Snippet B
List<int> a = new List<int>();
a.Add(4);
a.Add(6);
int b = a[0];
我们信任 IL,所以
Snippet A IL
IL_0000: nop
IL_0001: newobj System.Collections.Generic.List<System.Int32>..ctor
IL_0006: stloc.0 // a
IL_0007: ldloc.0 // a
IL_0008: ldc.i4.4
IL_0009: callvirt System.Collections.Generic.List<System.Int32>.Add
IL_000E: nop
IL_000F: ldloc.0 // a
IL_0010: ldc.i4.6
IL_0011: callvirt System.Collections.Generic.List<System.Int32>.Add
IL_0016: nop
IL_0017: ldloc.0 // a
IL_0018: call System.Linq.Enumerable.First
IL_001D: stloc.1 // b
IL_001E: ret
and
Snippet B IL
IL_0000: nop
IL_0001: newobj System.Collections.Generic.List<System.Int32>..ctor
IL_0006: stloc.0 // a
IL_0007: ldloc.0 // a
IL_0008: ldc.i4.4
IL_0009: callvirt System.Collections.Generic.List<System.Int32>.Add
IL_000E: nop
IL_000F: ldloc.0 // a
IL_0010: ldc.i4.6
IL_0011: callvirt System.Collections.Generic.List<System.Int32>.Add
IL_0016: nop
IL_0017: ldloc.0 // a
IL_0018: ldc.i4.0
IL_0019: callvirt System.Collections.Generic.List<System.Int32>.get_Item
IL_001E: stloc.1 // b
IL_001F: ret
片段 B 产生了一个命令更多的 IL,但最终哪种方法更快呢?
你可以自己检查一下:
static void Main()
{
List<long> resultsFirst = new List<long>();
List<long> resultsIndex = new List<long>();
Stopwatch s = new Stopwatch();
for (int z = 0; z < 100; z++)
{
List<int>[] lists = new List<int>[10000];
int temp = 0;
for (int i = 0; i < lists.Length; i++)
lists[i] = new List<int>() { 4, 6 };
s.Restart();
for (int i = 0; i < lists.Length; i++)
temp = lists[i].First();
s.Stop();
resultsFirst.Add(s.ElapsedTicks);
s.Restart();
for (int i = 0; i < lists.Length; i++)
temp = lists[i][0];
s.Stop();
resultsIndex.Add(s.ElapsedTicks);
}
Console.WriteLine("LINQ First() : " + resultsFirst.Average());
Console.WriteLine(Environment.NewLine);
Console.WriteLine("By index : " + resultsIndex.Average());
Console.ReadKey();
}
释放模式下的输出:
LINQ 首先():367
按指数:84
调试模式下的输出:
LINQ 首先():401
按指数:177
P.S.
First方法的源代码为:
public static TSource First<TSource>(this IEnumerable<TSource> source)
{
IList<TSource> list = source as IList<TSource>;
if (list != null)
{
if (list.Count > 0)
{
return list[0];
}
}
else
{
using (IEnumerator<TSource> enumerator = source.GetEnumerator())
{
if (enumerator.MoveNext())
{
return enumerator.Current;
}
}
}
}
铸造作业source as IList<TSource>
或者创建一个 Enumerator 对象很可能是原因First()
速度要慢得多。
P.S.
考虑到这一点,我不建议总是使用索引器,因为它有时可能会产生可读性较差的代码。通常可读性比微观优化更重要。
例如:
var lastEmployee = employees[employees.Count - 1]; // and even
var lastEmployee = employees[^1]; // C#8
可读性低于:
var lastEmployee = employees.Last();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)