2009-07-16 12 views
5

वहाँ लाइनrichtextbox लाइनों को पढ़ने के दौरान क्यों foreach पाश के लिए की तुलना में तेजी है

1 से RichTextBox लाइन से डेटा पढ़ने के लिए दो तरीके) का उपयोग कर रहे हैं एक एक RichTextBox

String s=String.Empty; 
for(int i=0;i<richtextbox.lines.length;i++) 
{ 
    s=richTextBox.Lines[i] 
} 

की तर्ज लूप करने के लिए पाश के लिए 2) एक foreach पाश का उपयोग richTextBox.Lines संग्रह

String s=String.Empty; 
    foreach(string str in txtText.Lines) 
    { 
     s=str; 
    } 

वहाँ प्रदर्शन में एक बड़ा फर्क है जब हम foreach पाश का उपयोग richtextbox के लिए सरणी संग्रह की गणना करने में है की गणना करने में।

मैंने 15000 लाइनों के साथ प्रयास किया। लूप को 15000 लाइनों तक लूप करने के लिए 8 मिनट लग गए। इस दौरान फोरैच ने इसे गणना करने के लिए एक सेकंड का अंश लिया।

यह व्यवहार क्यों है?

उत्तर

10

जैसा कि मेहर्डद ने नोट किया, Lines संपत्ति तक पहुंचने में काफी समय लगता है। आप यहाँ सावधान रहने की जरूरत है - आप इस समय प्रत्येक चरण में दो बार यह पहुँच बना रहे हैं:

String s = String.Empty; 
for (int i = 0; i < richTextBox.Lines.Length; i++) 
{ 
    s = richTextBox.Lines[i]; 
} 

यहां तक ​​कि अगर आप इस तरह पाश के शरीर में पहुंच को हटा:

String s = String.Empty; 
for (int i = 0; i < richTextBox.Lines.Length; i++) 
{ 
} 

आप अभी भीLines पर पहुंचने के लिए प्रत्येक पुनरावृत्ति पर यह देखने के लिए कि क्या आप समाप्त कर चुके हैं!

आप foreach नहीं करना चाहते हैं, तो आप सिर्फ एक बार Lines लाने कर सकते हैं:

string[] lines = richTextBox.Lines; 
for (int i = 0; i < lines.Length; i++) 
{ 
    s = lines[i]; 
} 

व्यक्तिगत तौर पर मैं foreach पसंद करते हैं जब तक आप वास्तव में सूचकांक की जरूरत है, हालांकि :)

+0

यदि यह समस्या है तो यह दो बार पहुंच रहा है, तो इसे केवल दो बार तक नहीं लेना चाहिए। लेकिन उसका अंतर एक मिनट के एक अंश बनाम 8 मिनट है। – barlop

+1

@barlop: नहीं, यह एक या दो बार के बीच का अंतर नहीं है, यह एक बार और एक बार प्रति पंक्ति के बीच का अंतर है। –

10

मुझे लगता है कि Lines संपत्ति हर बार जब आप इसे एक्सेस करना चाहते हैं तो पुन: गणना की जाती है। नतीजतन, foreach विधि केवल एक बार गणना करता है, जबकि हर बार आपका संदर्भ Lines[i] यह पूरी चीज का फिर से मूल्यांकन कर रहा है। Lines संपत्ति का परिणाम कैशिंग और फिर से देखने का प्रयास करें:

String s = String.Empty; 
var lines = richtextbox.Lines; 
for(int i = 0; i < lines.Length; i++) 
{ 
    s = lines[i]; 
} 

वैसे, आपके सवाल का एक अंतर्निहित धारणा है कि foreach हमेशा for की तुलना में धीमी है बनाता है। यह हमेशा सही नहीं होता।

+0

लेकिन फिर क्यों यह इतना है फास्टैच का उपयोग कर तेजी से। – Rohit

+3

फ़ोरैच 'सिंगल्स' संपत्ति में एक कॉल में अनुवाद करेगा। यह 'GetEnumerator()' पर कॉल करता है और केवल परिणामी गणनाकर्ता का उपयोग करता है। 'लाइन्स' संपत्ति को फिर कभी नहीं बुलाया जाता है। –

+4

+1 टेक्स्टबॉक्स बॉक्स से विरासत में दी गई लाइन्स प्रॉपर्टी, टेक्स्ट प्रॉपर्टी को पढ़ती है और इसके माध्यम से लूप करती है, चरित्र द्वारा चरित्र, उन्हें पंक्तियों में विभाजित करने के लिए। कॉलिंग कि 30k बार (15k loops, लंबाई और पढ़ने के मूल्य की जांच करने के लिए दो बार) इसे एक बार कॉल करने से धीमा हो जाएगा। – sisve

3

शायद क्योंकि टेक्स्टबॉक्स में अगली पंक्ति ढूंढने में समय लगता है। जब आप पहले मामले में अनुक्रमण द्वारा यादृच्छिक-पहुंच का उपयोग करते हैं, तो उसे उस रेखा को खरोंच से मिलना चाहिए। जब पुनरावृत्ति आंतरिक रूप से foreach द्वारा किया जाता है, तो यह राज्य को बनाए रख सकता है और तुरंत अगली पंक्ति ढूंढ सकता है।

यह ओ (एन^2) समय में पहला मामला चलाना चाहिए, जबकि ओ (एन) में दूसरा रन।

+0

"s = richTextBox.Lines [i]" को हटाने के बाद भी, यह बहुत समय लगा। मुझे आश्चर्य हुआ कि बस इतनी देर लग रही है। – Rohit

+0

मेरा जवाब देखें कि यह लाइन को हटाने के बाद भी धीमी क्यों है। –

0

क्या यह हो सकता है कि प्रत्येक पंक्ति को प्रत्येक लूप पर एक नई स्ट्रिंग वेरिएबल (str) में कॉपी किया जा रहा हो? मैं यहाँ guissing हूँ, लेकिन आप शायद इस कोड

String s = String.Empty; 
for (int i = 0; i < richTextBox.Lines.Length; i++) 
{ 
    string str = richTextBox.Lines[i]; 
    s = str; 
} 
+1

नहीं, इसके साथ कुछ करने के लिए मुझे कुछ भी नहीं मिला है। चर के लिए असाइनमेंट लगभग मुफ्त है। –

0

.NET Reflector साथ सिद्धांत सत्यापित कर सकता निर्धारित करने के लिए क्यों आप प्रदर्शन आप की उम्मीद नहीं है देख रहे हैं बहुत उपयोगी है।

इसे Linesget एक्सेसर को देखने का प्रयास करें ताकि यह देखने के लिए कि वास्तव में आप इसे कब तक पहुंचते हैं।