2013-10-09 1 views
2

어떤 접근 방식이 더 빠르거나 둘 다 같은 IL로 컴파일합니까?루프를 반복하면 루프 문 외부에서 반복 컬렉션을 파생시키는 것이 더 빠릅니까?

 var myCollection = new Dictionary<string, string>(){{"a", "aa"}, {"b", "bb"}, {"c", "bb"}}; 
     foreach (var uniqueItem in myCollection.Values.Distinct()) 
     { 
      //do something 
     } 

     var myCollection = new Dictionary<string, string>() { { "a", "aa" }, { "b", "bb" }, { "c", "bb" } }; 
     var uniqueItems = myCollection.Values.Distinct(); 
     foreach (var uniqueItem in uniqueItems) 
     { 
      //do something 
     } 

답변

2

릴리스 모드에서 동일한 IL 수율 및 성능합니다 (uniqueItems 가변 추후 사용하지 않는 가정) 같은 것 모두.

디버그에서 당신은 foreach는을 시작하기 전에 또 다른 과제를 볼 수 있습니다.

편집 -

private static void V1(Dictionary<string, string> myCollection) 
{ 
    foreach (var uniqueItem in myCollection.Values.Distinct()) 
    { 
    } 
} 

IL

를 생성은 컴파일로 :

.method private hidebysig static void V1(class [mscorlib]System.Collections.Generic.Dictionary`2<string, string> myCollection) cil managed 
{ 
    .maxstack 2 
    .locals init (
     [0] string uniqueItem, 
     [1] class [mscorlib]System.Collections.Generic.IEnumerator`1<string> CS$5$0000, 
     [2] bool CS$4$0001) 
    L_0000: nop 
    L_0001: nop 
    L_0002: ldarg.0 
    L_0003: callvirt instance class [mscorlib]System.Collections.Generic.Dictionary`2/ValueCollection<!0, !1> [mscorlib]System.Collections.Generic.Dictionary`2<string, string>::get_Values() 
    L_0008: call class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0> [System.Core]System.Linq.Enumerable::Distinct<string>(class [mscorlib]System.Collections.Generic.IEnumerable`1<!!0>) 
    L_000d: callvirt instance class [mscorlib]System.Collections.Generic.IEnumerator`1<!0> [mscorlib]System.Collections.Generic.IEnumerable`1<string>::GetEnumerator() 
    L_0012: stloc.1 
    L_0013: br.s L_001e 
    L_0015: ldloc.1 
    L_0016: callvirt instance !0 [mscorlib]System.Collections.Generic.IEnumerator`1<string>::get_Current() 
    L_001b: stloc.0 
    L_001c: nop 
    L_001d: nop 
    L_001e: ldloc.1 
    L_001f: callvirt instance bool [mscorlib]System.Collections.IEnumerator::MoveNext() 
    L_0024: stloc.2 
    L_0025: ldloc.2 
    L_0026: brtrue.s L_0015 
    L_0028: leave.s L_003a 
    L_002a: ldloc.1 
    L_002b: ldnull 
    L_002c: ceq 
    L_002e: stloc.2 
    L_002f: ldloc.2 
    L_0030: brtrue.s L_0039 
    L_0032: ldloc.1 
    L_0033: callvirt instance void [mscorlib]System.IDisposable::Dispose() 
    L_0038: nop 
    L_0039: endfinally 
    L_003a: nop 
    L_003b: ret 
    .try L_0013 to L_002a finally handler L_002a to L_003a 
} 
으로는 별개의에 대한 호출이 * L_0008 *에 아무 코드가 이상 이동하지 볼 수 있습니다

그것은 단지 한 번 부름을 의미합니다.

+0

IL에서 디버그 모드의 추가 할당은 반복 횟수에 관계없이 한 번 수행됩니까? –

+0

예, 메소드를 다시 호출하지 않고 * myCollection.Values.Distinct() * 값을 스택에 저장합니다. – Elisha

+0

큰 감사 ... –

관련 문제