नियंत्रण संरचनाओं के लिए 'C में' और 'foreach' के लिए प्रदर्शन अंतर


105

कौन सा कोड स्निपेट बेहतर प्रदर्शन देगा? नीचे दिए गए कोड सेगमेंट C # में लिखे गए थे।

1।

for(int counter=0; counter<list.Count; counter++)
{
    list[counter].DoSomething();
}

2।

foreach(MyType current in list)
{
    current.DoSomething();
}

31
मुझे लगता है कि यह वास्तव में कोई फर्क नहीं पड़ता। यदि आपको प्रदर्शन की समस्या हो रही है, तो यह निश्चित रूप से इसके कारण नहीं है। ऐसा नहीं है कि आपको सवाल नहीं पूछना चाहिए ...
darasd

2
जब तक आपका ऐप बहुत ही परफॉरमेंस क्रिटिकल नहीं होगा, मैं इस बारे में चिंता नहीं करूँगा। साफ और आसानी से समझने योग्य कोड के लिए बेहतर है।
फॉर्च्यूननर

2
यह मुझे चिंतित करता है कि यहाँ पर कुछ उत्तर ऐसे लोगों द्वारा पोस्ट किए गए प्रतीत होते हैं, जिनके मस्तिष्क में कहीं भी पुनरावृति की अवधारणा नहीं है, और इसलिए एन्यूमरेटर या पॉइंटर्स की कोई अवधारणा नहीं है।
एड जेम्स

3
वह दूसरा कोड संकलित नहीं करेगा। System.Object का कोई भी सदस्य नहीं है जिसे 'मूल्य' कहा जाता है (जब तक कि आप वास्तव में दुष्ट नहीं हैं, इसे एक विस्तार विधि के रूप में परिभाषित किया है और प्रतिनिधियों की तुलना कर रहे हैं)। जोर से अपने foreach टाइप करें।
ट्रिलियन

1
पहला कोड या तो संकलित नहीं करेगा, जब तक कि listवास्तव में इस प्रकार के countसदस्य के बजाय एक सदस्य न हो Count
जॉन स्कीट

जवाबों:


130

खैर, यह आंशिक रूप से सटीक प्रकार पर निर्भर करता है list। यह आपके द्वारा उपयोग किए जा रहे सटीक CLR पर भी निर्भर करेगा।

यह किसी भी तरह से महत्वपूर्ण है या नहीं यह इस बात पर निर्भर करेगा कि आप लूप में कोई वास्तविक काम कर रहे हैं या नहीं। लगभग सभी मामलों में, प्रदर्शन का अंतर महत्वपूर्ण नहीं होगा, लेकिन पठनीयता का अंतर foreachलूप के अनुकूल है ।

मैं व्यक्तिगत रूप से "यदि" से बचने के लिए LINQ का उपयोग करूंगा:

foreach (var item in list.Where(condition))
{
}

संपादित करें: यदि आप में से जो लोग दावा है कि एक से अधिक पुनरावृत्ति कर रहे हैं के लिए List<T>के साथ foreachके रूप में एक ही कोड का उत्पादन forपाश, यहाँ के सबूत है कि यह नहीं करता है:

static void IterateOverList(List<object> list)
{
    foreach (object o in list)
    {
        Console.WriteLine(o);
    }
}

का उत्पादन करता है:

.method private hidebysig static void  IterateOverList(class [mscorlib]System.Collections.Generic.List`1<object> list) cil managed
{
  // Code size       49 (0x31)
  .maxstack  1
  .locals init (object V_0,
           valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object> V_1)
  IL_0000:  ldarg.0
  IL_0001:  callvirt   instance valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<!0> class [mscorlib]System.Collections.Generic.List`1<object>::GetEnumerator()
  IL_0006:  stloc.1
  .try
  {
    IL_0007:  br.s       IL_0017
    IL_0009:  ldloca.s   V_1
    IL_000b:  call       instance !0 valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::get_Current()
    IL_0010:  stloc.0
    IL_0011:  ldloc.0
    IL_0012:  call       void [mscorlib]System.Console::WriteLine(object)
    IL_0017:  ldloca.s   V_1
    IL_0019:  call       instance bool valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>::MoveNext()
    IL_001e:  brtrue.s   IL_0009
    IL_0020:  leave.s    IL_0030
  }  // end .try
  finally
  {
    IL_0022:  ldloca.s   V_1
    IL_0024:  constrained. valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<object>
    IL_002a:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_002f:  endfinally
  }  // end handler
  IL_0030:  ret
} // end of method Test::IterateOverList

संकलक अलग-अलग सरणियों का इलाज करता है , एक foreachलूप को मूल रूप से लूप में परिवर्तित करता है for, लेकिन नहीं List<T>। यहाँ एक सरणी के लिए समान कोड है:

static void IterateOverArray(object[] array)
{
    foreach (object o in array)
    {
        Console.WriteLine(o);
    }
}

// Compiles into...

.method private hidebysig static void  IterateOverArray(object[] 'array') cil managed
{
  // Code size       27 (0x1b)
  .maxstack  2
  .locals init (object V_0,
           object[] V_1,
           int32 V_2)
  IL_0000:  ldarg.0
  IL_0001:  stloc.1
  IL_0002:  ldc.i4.0
  IL_0003:  stloc.2
  IL_0004:  br.s       IL_0014
  IL_0006:  ldloc.1
  IL_0007:  ldloc.2
  IL_0008:  ldelem.ref
  IL_0009:  stloc.0
  IL_000a:  ldloc.0
  IL_000b:  call       void [mscorlib]System.Console::WriteLine(object)
  IL_0010:  ldloc.2
  IL_0011:  ldc.i4.1
  IL_0012:  add
  IL_0013:  stloc.2
  IL_0014:  ldloc.2
  IL_0015:  ldloc.1
  IL_0016:  ldlen
  IL_0017:  conv.i4
  IL_0018:  blt.s      IL_0006
  IL_001a:  ret
} // end of method Test::IterateOverArray

दिलचस्प बात यह है कि, मुझे यह C # 3 युक्ति में कहीं भी प्रलेखित नहीं मिला ...


हित के बाहर, सूची के साथ परिदृश्य <टी> ऊपर ... क्या यह अन्य संग्रह पर भी लागू होता है? इसके अलावा, आप इसे कैसे जानते हैं (बिना किसी द्वेष के जिसका कोई भी उद्देश्य हो) ... जैसा कि आपने इस प्रश्न का उत्तर देने की कोशिश करते हुए, वास्तव में इस पर ठोकर खाई थी, कुछ समय पहले? यह ऐसा है ... यादृच्छिक / गुप्त :)
Pure.Krome

5
मुझे कुछ समय के लिए सरणी ऑप्टिमाइज़ेशन के बारे में पता है - सरणियाँ संग्रह का एक "मूल" प्रकार हैं; सी # संकलक पहले से ही उनके बारे में गहराई से जानते हैं, इसलिए यह उन्हें अलग तरह से व्यवहार करने के लिए समझ में आता है। संकलक के पास कोई विशेष ज्ञान नहीं है (और नहीं होना चाहिए) List<T>
जॉन स्कीट

चीयर्स :) और हाँ ... सरणी के पहले संग्रह की अवधारणा थी जो मुझे सालों पहले और सालों पहले यूनी में सिखाई गई थी। इसलिए यह समझ में आएगा कि कंपाइलर स्मार्ट है (यदि नहीं) सबसे आदिम प्रकार का संग्रह। फिर से खुश हो जाओ!
प्योर.क्रोम

3
@JonSkeet सूची पुनरावृत्ति को अनुकूलित करना जब पुनरावृत्ति के दौरान सूची को संशोधित किया जाता है तो व्यवहार को बदल देता है। आप अपवाद-अगर-संशोधित खो देते हैं। यह अभी भी अनुकूलन करना संभव है, लेकिन यह जांचने की आवश्यकता है कि कोई संशोधन नहीं होता है (अन्य थ्रेड्स पर, मुझे लगता है)।
क्रेग गिदनी

5
@VeeKeyBee: तो 2004 में Microsoft ने कहा था कि) क) चीजें बदल जाती हैं; ख) काम कर रही करना होगा छोटे प्रत्येक यात्रा पर काम की मात्रा इस महत्वपूर्ण होने के लिए। ध्यान दें कि foreachएक सरणी पर forवैसे भी बराबर है । हमेशा पहले पठनीयता के लिए कोड, फिर केवल सूक्ष्म-अनुकूलन जब आपके पास सबूत है कि यह एक औसत दर्जे का प्रदर्शन लाभ देता है।
जॉन स्कीट

15

एक forलूप को इसके बराबर कोड करने के लिए संकलित किया जाता है:

int tempCount = 0;
while (tempCount < list.Count)
{
    if (list[tempCount].value == value)
    {
        // Do something
    }
    tempCount++;
}

जहां एक foreachलूप को लगभग इसके बराबर कोड करने के लिए संकलित किया जाता है:

using (IEnumerator<T> e = list.GetEnumerator())
{
    while (e.MoveNext())
    {
        T o = (MyClass)e.Current;
        if (row.value == value)
        {
            // Do something
        }
    }
}

इसलिए जैसा कि आप देख सकते हैं, यह सब इस बात पर निर्भर करेगा कि एन्यूमरेटर को कैसे सूचीबद्ध किया जाता है बनाम कैसे कार्यान्वित किया जाता है। जैसा कि यह पता चलता है कि सरणियों के आधार पर प्रकार के लिए एन्यूमरेटर को आम तौर पर कुछ इस तरह लिखा जाता है:

private static IEnumerable<T> MyEnum(List<T> list)
{
    for (int i = 0; i < list.Count; i++)
    {
        yield return list[i];
    }
}

तो जैसा कि आप देख सकते हैं, इस उदाहरण में यह बहुत अधिक अंतर नहीं करेगा, हालांकि एक लिंक की गई सूची के लिए एनुमर शायद कुछ इस तरह दिखाई देगा:

private static IEnumerable<T> MyEnum(LinkedList<T> list)
{
    LinkedListNode<T> current = list.First;
    do
    {
        yield return current.Value;
        current = current.Next;
    }
    while (current != null);
}

में नेट आपको लगता है कि LinkedList <टी> वर्ग यहां तक कि एक इंडेक्सर, नहीं है तो आप किसी लिंक किए गए सूची में पाश के लिए अपने ऐसा करने में सक्षम नहीं होगा मिलेगा; लेकिन अगर आप कर सकते हैं, तो इंडेक्सर को ऐसा लिखना होगा:

public T this[int index]
{
       LinkedListNode<T> current = this.First;
       for (int i = 1; i <= index; i++)
       {
            current = current.Next;
       }
       return current.value;
}

जैसा कि आप देख सकते हैं, इस बार एक लूप में कॉल करना एक एन्यूमरेटर का उपयोग करने की तुलना में बहुत धीमा होने वाला है जो यह याद रख सकता है कि यह सूची में कहां है।


12

अर्ध-मान्य करने के लिए एक आसान परीक्षा। मैंने एक छोटा सा परीक्षण किया, बस देखने के लिए। यहाँ कोड है:

static void Main(string[] args)
{
    List<int> intList = new List<int>();

    for (int i = 0; i < 10000000; i++)
    {
        intList.Add(i);
    }

    DateTime timeStarted = DateTime.Now;
    for (int i = 0; i < intList.Count; i++)
    {
        int foo = intList[i] * 2;
        if (foo % 2 == 0)
        {
        }
    }

    TimeSpan finished = DateTime.Now - timeStarted;

    Console.WriteLine(finished.TotalMilliseconds.ToString());
    Console.Read();

}

और यहाँ फॉर्च्यून अनुभाग है:

foreach (int i in intList)
{
    int foo = i * 2;
    if (foo % 2 == 0)
    {
    }
}

जब मैंने एक फॉर्च्यूनर के साथ इसके लिए प्रतिस्थापित किया - फॉर्चैक 20 मिलीसेकंड तेजी से था - लगातार । के लिए 135-139ms था, जबकि फॉरेक्स 113-119ms था। मैंने कई बार आगे और पीछे स्वैप किया, यह सुनिश्चित करते हुए कि यह कुछ प्रक्रिया नहीं थी जो बस में किक की गई थी।

हालांकि, जब मैंने फू और इफ स्टेटमेंट को हटा दिया, तो इसके लिए 30 ms (foreach 88ms और 59ms के लिए) द्वारा तेज़ किया गया था। वे दोनों खाली गोले थे। मैं मान रहा हूँ कि वास्तव में फॉरेक्स एक वैरिएबल पारित कर दिया है, जहाँ फ़ॉर वैरिएबल केवल एक वैरिएबल बढ़ा रहा था। अगर मैंने जोड़ा

int foo = intList[i];

फिर लगभग 30ms तक धीमा हो जाता है। मैं मान रहा हूँ कि इसके साथ foo बनाने और सरणी में वैरिएबल को हथियाने और इसे foo को असाइन करना था। यदि आप केवल intList [i] का उपयोग करते हैं, तो आपके पास वह जुर्माना नहीं है।

सभी ईमानदारी में .. मैं उम्मीद करता था कि सभी परिस्थितियों में फॉर्च्यूनर थोड़ा धीमा होगा, लेकिन अधिकांश अनुप्रयोगों में यह पर्याप्त नहीं होगा।

संपादित करें: यहाँ Jons सुझावों का उपयोग करते हुए नया कोड है (134217728, SystemOutOfMemory अपवाद को फेंकने से पहले आपके पास सबसे बड़ा int हो सकता है):

static void Main(string[] args)
{
    List<int> intList = new List<int>();

    Console.WriteLine("Generating data.");
    for (int i = 0; i < 134217728 ; i++)
    {
        intList.Add(i);
    }

    Console.Write("Calculating for loop:\t\t");

    Stopwatch time = new Stopwatch();
    time.Start();
    for (int i = 0; i < intList.Count; i++)
    {
        int foo = intList[i] * 2;
        if (foo % 2 == 0)
        {
        }
    }

    time.Stop();
    Console.WriteLine(time.ElapsedMilliseconds.ToString() + "ms");
    Console.Write("Calculating foreach loop:\t");
    time.Reset();
    time.Start();

    foreach (int i in intList)
    {
        int foo = i * 2;
        if (foo % 2 == 0)
        {
        }
    }

    time.Stop();

    Console.WriteLine(time.ElapsedMilliseconds.ToString() + "ms");
    Console.Read();
}

और यहाँ परिणाम हैं:

डेटा जनरेट करना। लूप के लिए गणना: 2458ms फॉरेस्ट लूप की गणना: 2005ms

उन्हें देखने के लिए चारों ओर स्वैप करना कि क्या यह चीजों के क्रम से संबंधित है, समान परिणाम (लगभग) देता है।


6
स्टॉपवॉच को DateTime.Now के मुकाबले इस्तेमाल करना बेहतर है - और मैं किसी भी रन पर भरोसा नहीं करूंगा, ईमानदार होने के लिए।
जॉन स्कीट

8
आपका फ़ॉरच्यू लूप तेजी से चल रहा है क्योंकि 'फॉर' प्रत्येक पुनरावृत्ति की स्थिति का मूल्यांकन करता है। आपके उदाहरण के मामले में, यह एक अतिरिक्त विधि कॉल के लिए बनाता है (सूची प्राप्त करने के लिए)। संक्षेप में, आप कोड के दो अलग-अलग टुकड़ों को बेंचमार्क कर रहे हैं, इसलिए आपके अजीब परिणाम हैं। कोशिश 'int max = intlist.Count; for (int i = 0; i <max; i ++) ... 'और' for 'लूप हमेशा तेज गति से चलेगा, जैसी कि उम्मीद थी!
एआर

1
संकलन के बाद, प्रिमिटिव्स के साथ काम करने के लिए foreach और बिल्कुल उसी चीज़ के लिए ऑप्टिमाइज़ करते हैं। यह तब तक नहीं है जब तक आप सूची <T> का परिचय नहीं देते हैं कि वे गति में भिन्न (बहुत) हैं।
एंथनी रसेल

9

नोट: यह उत्तर जावा से अधिक # C पर लागू होता है, क्योंकि C # में कोई अनुक्रमणिका नहीं होती है LinkedLists, लेकिन मुझे लगता है कि यह सामान्य बिंदु रखता है।

यदि listआप के साथ काम कर रहे हैं एक होता है LinkedList, इंडेक्सर-कोड (के प्रदर्शन सरणी शैली तक पहुँचने) का उपयोग कर की तुलना में बहुत खराब है IEnumeratorसे foreach, बड़े सूचियों के लिए।

जब आप LinkedListअनुक्रमणिका सिंटैक्स का उपयोग करते हुए तत्व 10.000 तक पहुंचते हैं list[10000], तो लिंक की गई सूची सिर के नोड पर शुरू हो जाएगी, और Next-पॉइंटर्स को दस हजार बार पार कर लेगी, जब तक कि यह सही वस्तु तक नहीं पहुंचता। जाहिर है, यदि आप एक लूप में ऐसा करते हैं, तो आपको मिलेगा:

list[0]; // head
list[1]; // head.Next
list[2]; // head.Next.Next
// etc.

जब आप कॉल करते हैं GetEnumerator( forachसंक्षेप में -syntax का उपयोग करके ), तो आपको एक IEnumeratorऑब्जेक्ट मिलेगा जो सिर के नोड के लिए एक संकेतक है। हर बार जब आप कॉल करते हैं MoveNext, तो पॉइंटर को अगले नोड पर ले जाया जाता है, जैसे:

IEnumerator em = list.GetEnumerator();  // Current points at head
em.MoveNext(); // Update Current to .Next
em.MoveNext(); // Update Current to .Next
em.MoveNext(); // Update Current to .Next
// etc.

जैसा कि आप देख सकते हैं, LinkedListएस के मामले में , सरणी इंडेक्सर विधि धीमी और धीमी हो जाती है , जितनी अधिक बार आप लूप करते हैं (इसे एक ही हेड पॉइंटर से बार-बार गुजरना पड़ता है)। जबकि IEnumerableनिरंतर समय में बस संचालित होती है।

बेशक, जैसा कि जॉन ने कहा कि यह वास्तव में के प्रकार पर निर्भर करता है list, अगर यह listएक नहीं है LinkedList, लेकिन एक सरणी है, तो व्यवहार पूरी तरह से अलग है।


4
.NET में लिंक्डलिस्ट में इंडेक्सर नहीं है, इसलिए यह वास्तव में एक विकल्प नहीं है।
जॉन स्कीट

ओह, यह अच्छी तरह से उस समस्या को हल करता है, तो :-) मैं सिर्फ LinkedList<T>MSDN पर डॉक्स के माध्यम से देख रहा हूं , और इसमें एक बहुत अच्छा एपीआई है। सबसे महत्वपूर्ण बात, यह एक get(int index)विधि नहीं है , जैसे जावा करता है। फिर भी, मुझे लगता है कि बिंदु अभी भी किसी भी अन्य सूची जैसी डेटा संरचना के लिए है जो एक इंडेक्सर को उजागर करता है जो एक विशिष्ट की तुलना में धीमा है IEnumerator
टॉम लोखर्स्ट

2

जैसे कि अन्य लोगों ने उल्लेख किया है कि प्रदर्शन वास्तव में ज्यादा मायने नहीं रखता है, लूप में उपयोग IEnumerable/ IEnumeratorउपयोग के कारण फॉरच हमेशा थोड़ा धीमा रहेगा । कंपाइलर उस इंटरफ़ेस पर कॉल में निर्माण का अनुवाद करता है और प्रत्येक चरण के लिए एक संपत्ति + को फॉरेक्स निर्माण में कहा जाता है।

IEnumerator iterator = ((IEnumerable)list).GetEnumerator();
while (iterator.MoveNext()) {
  var item = iterator.Current;
  // do stuff
}

यह C # में निर्माण के बराबर विस्तार है। आप कल्पना कर सकते हैं कि MoveNext और Current के कार्यान्वयन के आधार पर प्रदर्शन प्रभाव कैसे भिन्न हो सकते हैं। जबकि एक एक्सेस एक्सेस में, आपके पास वह निर्भरता नहीं है।


4
यह मत भूलो कि एक ऐरे एक्सेस और इंडेक्सर एक्सेस के बीच अंतर है। यदि सूची List<T>यहां है तो इंडेक्सर को कॉल करने की हिट (संभवतः इनबिल्ट) अभी भी है। ऐसा नहीं है कि यह एक नंगे धातु की पहुंच है।
जॉन स्कीट

सच सच! यह अभी तक एक और संपत्ति निष्पादन है और हम कार्यान्वयन की दया पर हैं।
चार्ल्स प्रकाश दासारी

1

पर्याप्त तर्क पढ़ने के बाद कि "पठनीयता के लिए फॉरच लूप को प्राथमिकता दी जानी चाहिए", मैं कह सकता हूं कि मेरी पहली प्रतिक्रिया "क्या" थी? पठनीयता, सामान्य रूप से, व्यक्तिपरक है और इस विशेष उदाहरण में और भी अधिक। प्रोग्रामिंग में पृष्ठभूमि वाले किसी व्यक्ति के लिए (व्यावहारिक रूप से, जावा से पहले की हर भाषा), लूप के लिए फोरच लूप की तुलना में पढ़ना बहुत आसान है। इसके अलावा, वही लोग दावा करते हैं कि फॉरच लूप अधिक पठनीय हैं, लिनाक और अन्य "सुविधाओं" के समर्थक भी हैं जो कोड को पढ़ने और बनाए रखने के लिए कठिन बनाते हैं, कुछ ऐसा जो उपरोक्त बिंदु को साबित करता है।

प्रदर्शन पर प्रभाव के बारे में, इस प्रश्न का उत्तर देखें ।

EDIT: C # (हैशसेट की तरह) में संग्रह हैं जिनका कोई इंडेक्सर नहीं है। इन संग्रहों में, foreach पुनरावृति करने के लिए एक ही रास्ता है और यह केवल मामले मैं इस पर इस्तेमाल किया जाना चाहिए लगता है के लिए


0

एक और दिलचस्प तथ्य है जो दोनों छोरों की गति का परीक्षण करते समय आसानी से याद किया जा सकता है: डिबग मोड का उपयोग करके संकलक को डिफ़ॉल्ट सेटिंग्स का उपयोग करके कोड को अनुकूलित करने की अनुमति नहीं देता है।

इसने मुझे दिलचस्प नतीजे पर पहुंचा दिया कि डिबग डिबग मोड की तुलना में अधिक तेज़ है। जबकि रिलीज़ मोड में फ़ॉरेस्ट की तुलना में ist तेज़ है। जाहिर है कि कंपाइलर के पास फॉर्च्यूप लूप की तुलना में लूप को ऑप्टिमाइज़ करने के बेहतर तरीके हैं जो कई मेथड कॉल्स से समझौता करता है। एक लूप के लिए इस तरह से मौलिक है कि यह संभव है कि यह सीपीयू द्वारा भी अनुकूलित हो।


0

आपके द्वारा दिए गए उदाहरण में, foreachलूप के बजाय लूप का उपयोग करना निश्चित रूप से बेहतर है for

मानक foreachनिर्माण एक सरल for-loop(2 चक्र प्रति चरण) की तुलना में तेज (1,5 चक्र प्रति चरण) हो सकता है , जब तक कि लूप को अनियंत्रित नहीं किया गया है (प्रति चरण 1.0 चक्र)।

हर रोज कोड के लिए तो, प्रदर्शन और अधिक जटिल उपयोग करने के लिए एक कारण नहीं है for, whileया do-whileनिर्माणों।

इस लिंक को देखें: http://www.codeproject.com/Articles/146797/Fast-and-Less-Fast-Loops-in-C


╔══════════════════════╦═══════════╦═══════╦════════════════════════╦═════════════════════╗
        Method         List<int>  int[]  Ilist<int> onList<Int>  Ilist<int> on int[] 
╠══════════════════════╬═══════════╬═══════╬════════════════════════╬═════════════════════╣
 Time (ms)             23,80      17,56  92,33                   86,90               
 Transfer rate (GB/s)  2,82       3,82   0,73                    0,77                
 % Max                 25,2%      34,1%  6,5%                    6,9%                
 Cycles / read         3,97       2,93   15,41                   14,50               
 Reads / iteration     16         16     16                      16                  
 Cycles / iteration    63,5       46,9   246,5                   232,0               
╚══════════════════════╩═══════════╩═══════╩════════════════════════╩═════════════════════╝


4
आपके द्वारा लिंक किए गए कोड प्रोजेक्ट लेख को आप फिर से पढ़ सकते हैं। यह एक दिलचस्प लेख है, लेकिन यह आपके पोस्ट के बिल्कुल विपरीत कहता है। इसके अलावा, आपके द्वारा पुनः सारणी की गई सारणी और सूची को सीधे या उनके IList इंटरफेस के माध्यम से एक्सेस करने के प्रदर्शन को माप रहा है। न ही सवाल से कोई लेना-देना है। :)
पॉल वॉल्स

0

आप इसके बारे में Deep .NET - part 1 Iteration में पढ़ सकते हैं

यह .NET स्रोत कोड से परिणाम (पहले आरंभिक के बिना) को कवर करता है।

उदाहरण के लिए - फॉरेस्ट लूप के साथ ऐरे इटरेशन: यहां छवि विवरण दर्ज करें

और - फ़ॉरच लूप के साथ सूची पुनरावृत्ति: यहां छवि विवरण दर्ज करें

और अंतिम परिणाम: यहां छवि विवरण दर्ज करें

यहां छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.