Non è una cattiva pratica ... dipende tutto da cosa sta facendo la funzione, e se il codice nella funzione deve essere all'interno di un ciclo o se può essere refactored al di fuori di un ciclo.
Una funzione è solo un insieme di istruzioni, quindi potresti teoricamente prendere le istruzioni di qualsiasi funzione e metterle direttamente all'interno del ciclo, e sostanzialmente hai la stessa cosa. Se quella serie di istruzioni è di aggiungere due più due, non hai molto di cui preoccuparti. Se quel set di istruzioni è di aprire una tabella di database di 10 milioni di righe, trova una riga, scrivi i valori su disco, chiudi la connessione e ripeti, quindi hai qualcosa su cui riflettere.
Spesso, indipendentemente dal tempo impiegato, potrebbe essere richiesto anche se non è performante. Altre volte, potresti davvero mettere delle cose stupide in un ciclo.
Prendiamo "aprire una tabella di database di 10 milioni di righe e scrivere i valori di ogni riga in un file" esempio.
Anello errato:
int count = GetFullCountFromSomewhere();
for (int i = 0 i < count; i++) {
GetMyRow(i);
WriteMyRow(i);
}
function GetMyRow(i) {
Table table = new Table();
table.Fill(someConnection);
Row row = table.Rows[i];
return row;
}
In quanto sopra, un'istanza di tabella (e tutto l'overhead associato) viene eseguita necessariamente per ogni iterazione.
Ciclo migliore:
Table table = GetMyTable()
for (int i = 0 i < table.Rows.count; i++) {
WriteMyRow(table.Rows[i]);
}
function GetMyTable(i) {
Table table = new Table();
table.Fill(someConnection);
return table;
}
o, forse anche meglio (dato che potrebbe essere ottimizzato internamente dal compilatore di lingue):
Table table = GetMyTable();
ForEach(var row in Table.Rows) {
WriteMyRow(row);
}
Quindi, puoi vedere alcuni modi in cui possiamo gestire il codice all'interno di un ciclo anziché configurarlo al di fuori del ciclo.
Questa è davvero l'unica cosa che vale la pena considerare, almeno su base giornaliera.