2013-07-17 33 views
3

我们可以通过下面的语句以下两条语句有什么区别?

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

计算过程,但整形暗示我,就像下面的语句

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

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

回答

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

的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 

原因是显而易见的,不是吗?

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