2008-09-04 7 views
12

में एक आईनेमेरेबल क्लास पर फोरच और लूप के बीच अंतर मुझे बताया गया है कि निम्न कोड ब्लॉक के बीच एक प्रदर्शन अंतर है।सी #

foreach (Entity e in entityList) 
{ 
.... 
} 

और

for (int i=0; i<entityList.Count; i++) 
{ 
    Entity e = (Entity)entityList[i]; 
    ... 
} 

जहां

List<Entity> entityList; 

मुझे कोई CLR हूँ उम्मीद है, लेकिन मैं क्या बताते हैं कि वे मूलतः एक ही कोड के लिए नीचे उबाल चाहिए कर सकते हैं से। क्या किसी के पास ठोस है (बिल्ली, मैं पैक गंदगी लेता हूं) साक्ष्य एक तरफ या दूसरा?

उत्तर

8

foreach एक गणक का एक उदाहरण बनाता है (GetEnumerator से लौटाया गया) और यह संख्याकर्ता फोरैच लूप के दौरान भी राज्य को बनाए रखता है। फिर यह बार-बार गणनाकर्ता पर अगली() ऑब्जेक्ट के लिए कॉल करता है और प्रत्येक ऑब्जेक्ट के लिए आपका कोड चलाता है।

वे किसी भी तरह से उसी कोड पर उबाल नहीं लेते हैं, वास्तव में, जो आप देखेंगे कि आपने अपना खुद का गणक लिखा है या नहीं।

9

Here एक अच्छा लेख है जो दो लूपों के बीच आईएल मतभेद दिखाता है।

पूर्वानुमान तकनीकी रूप से धीमा है, लेकिन उपयोग करने में आसान और पढ़ने में आसान है। जब तक प्रदर्शन महत्वपूर्ण नहीं होता है, मैं लूप के लिए फ़ोरैच लूप पसंद करता हूं।

0

मुझे लगता है कि एक संभावित स्थिति जहां आप प्रदर्शन लाभ प्राप्त कर सकते हैं यदि संख्यात्मक प्रकार का आकार और लूप स्थिति स्थिर है; उदाहरण के लिए:

const int ArraySize = 10; 
int[] values = new int[ArraySize]; 

//... 

for (int i = 0; i

इस मामले में, पाश शरीर की जटिलता पर निर्भर करता है, संकलक इनलाइन कॉल के साथ पाश को बदलने के लिए सक्षम हो सकता है। मुझे नहीं पता कि .NET कंपाइलर ऐसा करता है, और यदि यह संख्यात्मक प्रकार का आकार गतिशील है तो सीमित उपयोगिता है।

एक स्थिति जहां foreach बेहतर प्रदर्शन कर सकता है एक लिंक की गई सूची जैसे डेटा संरचनाओं के साथ जहां यादृच्छिक पहुंच सूची का पता लगाने का मतलब है; foreach द्वारा उपयोग किए जाने वाले गणक को संभवतः एक समय में एक आइटम फिर से चालू किया जाएगा, प्रत्येक एक्सेस ओ (1) और पूर्ण लूप ओ (एन) बनाते हुए, लेकिन इंडेक्सर को कॉल करना मतलब है कि सिर से शुरू करना और सही इंडेक्स पर आइटम ढूंढना; ओ (एन) ओ के लिए प्रत्येक लूप (एन^2)।

व्यक्तिगत रूप से मैं आमतौर पर इसके बारे में चिंता नहीं करता और foreach का उपयोग करता हूं, जब भी मुझे सभी वस्तुओं की आवश्यकता होती है और आइटम की अनुक्रमणिका की परवाह नहीं होती है। अगर मैं सभी वस्तुओं के साथ काम नहीं कर रहा हूं या मुझे वास्तव में इंडेक्स को जानना है, तो मैं के लिए उपयोग करता हूं। एकमात्र बार मैं इसे एक बड़ी चिंता के रूप में देख सकता था, लिंक्ड सूचियों जैसे संरचनाओं के साथ।

6

foreach नमूना मोटे तौर पर इस कोड से मेल खाती है:

using(IEnumerator<Entity> e = entityList.GetEnumerator()) { 
    while(e.MoveNext()) { 
     Entity entity = e.Current; 
     ... 
    } 
} 

वहाँ दो लागत यहाँ हैं कि भुगतान करने के लिए नहीं है पाश के लिए एक नियमित:

  1. द्वारा प्रगणक वस्तु आवंटन की लागत entityList.GetEnumerator()।
  2. सूची के प्रत्येक तत्व के लिए दो वर्चुअल विधियों की कॉल (MoveNext और Current) की लागत।
1

आवंटन के मामले में, this blogpost पर देखना बेहतर होगा। यह वास्तव में दिखाता है कि किस परिस्थिति में एक गणक को ढेर पर आवंटित किया जाता है।

3

एक बिंदु यहां चूक गया: एक सूची में एक गणना संपत्ति है, यह आंतरिक रूप से ट्रैक करता है कि इसमें कितने तत्व हैं।

एक आईनेमरेबल नहीं करता है।

यदि आप इंटरफ़ेस को प्रोग्राम करने के लिए प्रोग्राम करते हैं और गिनती विस्तार विधि का उपयोग करते हैं तो यह केवल तत्वों की गणना करने के लिए गणना करेगा।

हालांकि एक महत्वपूर्ण बिंदु हालांकि आईनेमरेबल में आप इंडेक्स द्वारा आइटम्स का उल्लेख नहीं कर सकते हैं।

तो यदि आप सूचियों और Arrays में लॉक करना चाहते हैं तो आप छोटे प्रदर्शन में वृद्धि कर सकते हैं।

यदि आप लचीलापन का उपयोग आईनामेरेबल को फोरैच और प्रोग्राम का उपयोग करना चाहते हैं। (linq और/या उपज वापसी के उपयोग की अनुमति)।

0
For Loop 
for loop is used to perform the opreration n times 
for(int i=0;i<n;i++) 
{ 
l=i; 
} 
foreach loop 

int[] i={1,2,3,4,5,6} 
foreach loop is used to perform each operation value/object in IEnumarable 
foreach(var k in i) 
{ 
l=k; 
}