In definitiva, la migliore risposta è testarla effettivamente. Crea un metodo che esegue il loop su un array vuoto con e senza prima controllare la lunghezza, chiama ogni 100.000 volte e controlla quale ha un tempo di esecuzione più veloce.
public void withCheck(Integer[] array) {
for (int i = 0; i < 100000; i++) {
if (array.length > 0) {
for (Integer i : array) {
// nothing to do.
}
}
}
}
public void withoutCheck(Integer[] array) {
for (int i = 0; i < 100000; i++) {
for (Integer i : array) {
// nothing to do.
}
}
}
public void test() {
long startTime = System.currentTimeMillis();
withCheck();
System.out.println("Time with check: " + (System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis();
withoutCheck();
System.out.println("Time without check: " + (System.currentTimeMillis() - startTime) + "ms");
}
Quando scrivo codice come questo, generalmente considero questo come un compromesso tra la leggibilità del codice e le prestazioni percepite o potenziali. In altre parole, l'aggiunta di un controllo if (count > 0)
influisce negativamente sulla leggibilità, anche se di una quantità molto piccola. Allora, qual è il guadagno? Presumo che ci sia poco o nessun vantaggio, ma come te, non l'ho ancora testato. Quello che posso dirti è che in tutti i miei anni di profilazione, non ho mai trovato il loop su un array vuoto per essere un collo di bottiglia.
Tecnicamente, dipende da come funziona l'iteratore. Per un ciclo foreach come quello che hai, stai creando un oggetto iteratore dietro le quinte. La mia aspettativa sarebbe, e ancora, questo non è verificato, è che l'oggetto iteratore FOR AN ARRAY sarebbe semplicemente implementato in questo modo (questo è Java, ma C # è probabilmente comparabile):
public class ArrayIterator<T> implements Iterator<T> {
private int next = 0;
public T next() {
return backingArray[next++];
}
public boolean hasNext() {
return next < backingArray.length;
}
}
Quindi iterare su un iteratore di questo tipo dovrebbe uscire molto rapidamente perché hasNext()
restituirà false. Si noti che è lo stesso controllo che farebbe la dichiarazione if
.
Ora se stai iterando su un elenco collegato, l'implementazione dovrebbe essere diversa. Se si controlla esplicitamente la dimensione, è possibile che si stia forzando a eseguire la scansione dell'elenco collegato. In Java, LinkedList.size()
controlla una variabile size
esplicita in modo che non dia l'elenco, ma non so in che modo .NET lo implementa.
Un altro modo di guardare questo è quanto è probabile che la collezione sia vuota? Se questo è un caso raro, allora se la teoria che iterating su un array vuoto richiede del tempo è vera, quindi aggiungere un controllo esplicito per vuoto per primo sarebbe solo più veloce se la raccolta è di solito vuota. In caso contrario, stai teoricamente rallentando il tuo caso medio per accelerare leggermente il tuo caso peggiore.
Ancora una volta, queste sono tutte teorie e i tempi sono a livello micro, quindi prendilo con un pizzico di sale.
TL; DR
Dipende dal tipo di raccolta, dalla piattaforma di runtime e dalla dimensione tipica della raccolta, ma intuitivamente, sembra improbabile che acceleri nella maggior parte delle situazioni. Ma l'unico modo per saperlo è testarlo.