2009-07-16 15 views
5

Ci sono due modi per leggere i dati dalla linea RichTextBox per rigaperché foreach è più veloce di ciclo for durante la lettura linee RichTextBox

1) utilizzare un ciclo for per scorrere le linee di un RichTextBox

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

2) utilizzare un ciclo foreach per enumerare richTextBox.Lines raccolta

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

C'è una grande differenza in termini di prestazioni quando usiamo ciclo foreach per enumerare la raccolta array per RichTextBox.

Ho provato con 15000 linee.per il ciclo ci sono voluti 8 minuti per eseguire il looping a 15000 linee. Intanto foreach ha impiegato una frazione di secondo per enumerarlo.

Perché questo comportamento è presente?

risposta

10

Come notato da Mehrdad, l'accesso alla proprietà Lines richiede molto tempo. È necessario essere attenti qui - si sta accedendo è due volte in ogni iterazione in questo momento:

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

Anche se si rimuove l'accesso nel corpo del ciclo come questo:

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

sei ancora accesso a Lines su ogni iterazione per vedere se hai finito!

Se non si desidera foreach, si può solo prendere Lines volta:

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

Personalmente preferisco il foreach a meno che non si ha realmente bisogno l'indice però :)

+0

se è l'accesso due volte che è il problema, allora non dovrebbe richiedere solo il doppio del tempo. Ma la sua differenza è di 8 minuti contro una frazione di secondo. – barlop

+1

@barlop: No, non è la differenza tra una o due volte, è la differenza tra una volta e una volta per riga. –

10

Penso che la proprietà Lines venga ricalcolata ogni volta che si desidera accedervi. Di conseguenza, il metodo foreach esegue il calcolo solo una volta, mentre ogni volta il tuo riferimento Lines[i] sta rivalutando il tutto. Prova cache il risultato di Lines proprietà e il controllo di nuovo:

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

Tra l'altro, la sua domanda fa un presupposto implicito che foreach è sempre più lento di for. Questo non è sempre vero.

+0

ma allora perché è così veloce usando foreach. – Rohit

+3

foreach si tradurrà in una singola chiamata alla proprietà 'Lines'. Chiama 'GetEnumerator()' e usa solo l'enumeratore risultante. La proprietà 'Lines' non viene mai più richiamata. –

+4

+1 La proprietà Lines, ereditata da TextBoxBase, legge la proprietà Text e scorre attraverso di essa, carattere per carattere, per dividerli in righe. Chiamare quel 30k volte (15k loop, due volte per controllare la lunghezza e leggere il valore) sarà più lento che chiamarlo una volta. – sisve

3

Probabilmente perché trovare la riga successiva nella casella di testo richiede tempo. Quando si utilizza l'accesso casuale mediante l'indicizzazione nel primo caso, deve trovare quella linea da zero. Quando l'iterazione viene eseguita internamente da foreach, può mantenere lo stato e trovare rapidamente la riga successiva.

Questo dovrebbe far funzionare il primo caso in O (n^2), mentre il secondo viene eseguito in O (n).

+0

anche dopo aver rimosso "s = richTextBox.Lines [i]", ci è voluto molto tempo. Mi chiedevo solo l'iterazione del tempo necessario. – Rohit

+0

Vedere la mia risposta per perché è ancora lento dopo aver rimosso quella linea. –

0

Potrebbe essere che ogni riga viene copiata in una nuova variabile di stringa (str) su ciascun ciclo? Sto guissing qui, ma probabilmente si potrebbe verificare la teoria con questo codice

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

No, non ho niente a che fare con questo temo. L'assegnazione alla variabile è praticamente gratuita. –

0

.NET Reflector è molto utile per determinare il motivo per cui che stai vedendo le prestazioni che non ti aspetti.

Fai un tentativo di guardare l'accessorio Linesget per vedere cosa effettivamente fa ogni volta che accedervi.

Problemi correlati