3

我们可以通过下面的语句来统计进程

var query = Process.GetProcesses()
             .Where(m => m.ProcessName.StartsWith("S")).Count();

但是 ReShaper 建议我喜欢以下声明

var query = Process.GetProcesses().Count(m => m.ProcessName.StartsWith("S"));

我的问题是......如果我考虑性能问题,哪个更好???

4

2 回答 2

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;

因此,第二条语句的性能稍好一些。

于 2013-07-17T13:37:02.830 回答
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 

原因很明显,不是吗?

执行时间的差异不是很大,但是第一个方法调用较少,所以看起来更好。

于 2013-07-17T14:19:18.480 回答