我们可以通过以下声明来计算过程
var query = Process.GetProcesses()
.Where(m => m.ProcessName.StartsWith("S")).Count();
但是ReShaper建议我跟随声明
var query = Process.GetProcesses().Count(m => m.ProcessName.StartsWith("S"));
我的问题是......如果考虑性能问题,哪一个更好?
答案 0 :(得分:4)
第一个语句将在内部创建WhereIterator
,它将迭代源并应用谓词。计算计算如下:
var iterator = new WhereArrayIterator<TSource>((TSource[]) source, predicate);
int num = 0;
using (IEnumerator<TSource> enumerator = iterator.GetEnumerator())
{
while (enumerator.MoveNext())
num++;
}
return num;
但是第二个语句不会创建迭代器 - 它将直接在源序列上迭代时应用谓词:
int num = 0;
foreach (TSource local in source)
{
if (predicate(local))
num++;
}
return num;
所以,第二个语句稍微表现更好。
答案 1 :(得分:1)
两个查询的IL结果是:
Process.GetProcesses().Count(m => m.ProcessName.StartsWith("S"));
IL_0001: call System.Diagnostics.Process.GetProcesses
IL_0006: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_000B: brtrue.s IL_0020
IL_000D: ldnull
IL_000E: ldftn b__0
IL_0014: newobj System.Func<System.Diagnostics.Process,System.Boolean>..ctor
IL_0019: stsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_001E: br.s IL_0020
IL_0020: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_0025: call System.Linq.Enumerable.Count
Process.GetProcesses().Where(m => m.ProcessName.StartsWith("S")).Count();
IL_0001: call System.Diagnostics.Process.GetProcesses
IL_0006: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_000B: brtrue.s IL_0020
IL_000D: ldnull
IL_000E: ldftn b__0
IL_0014: newobj System.Func<System.Diagnostics.Process,System.Boolean>..ctor
IL_0019: stsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_001E: br.s IL_0020
IL_0020: ldsfld UserQuery.CS$<>9__CachedAnonymousMethodDelegate1
IL_0025: call System.Linq.Enumerable.Where
IL_002A: call System.Linq.Enumerable.Count
b__0:
IL_0000: ldarg.0
IL_0001: callvirt System.Diagnostics.Process.get_ProcessName
IL_0006: ldstr "S"
IL_000B: callvirt System.String.StartsWith
IL_0010: stloc.0 // CS$1$0000
IL_0011: br.s IL_0013
IL_0013: ldloc.0 // CS$1$0000
IL_0014: ret
原因很明显,不是吗?
执行时间的差异不是很大,但第一个方法调用较少,所以看起来更好。