Nessuno dei due metodi mostra differenze significative. for
e RemoveAll
sembrano un po 'più veloci (più probabilmente perché si utilizza Remove
per la duplicazione dell'elenco e occorre ricrearlo ... utilizzando i tipi di valore, ciò significa anche il raddoppio della memoria necessaria). Ho fatto un po 'di profilazione:
public static void MethodA()
{
var list = new List<int>(Enumerable.Range(1, 10));
for (int i = list.Count - 1; i >= 0; i--)
{
if (list[i] > 5)
list.RemoveAt(i);
}
}
public static void MethodB()
{
var list = new List<int>(Enumerable.Range(1, 10));
foreach (var item in list.ToList())
{
if (item > 5)
list.Remove(item);
}
}
public static void MethodC()
{
var list = new List<int>(Enumerable.Range(1, 10));
list.RemoveAll(x => x > 5);
}
public static void Measure(string meas, Action act)
{
GC.Collect();
GC.WaitForPendingFinalizers();
var st = new Stopwatch();
st.Start();
for (var i = 0; i < 10000000; i++)
act();
st.Stop();
Console.WriteLine($"{meas}: {st.Elapsed}");
}
static void Main(string[] args)
{
Measure("A", MethodA);
Measure("B", MethodB);
Measure("C", MethodC);
}
Il risultato:
A: 00: 00: 04,1179163
B: 00: 00: 07,7417853
C: 00: 00: 04,3525255
Altre corse danno risultati ancora più simili (si noti che questo è per 10 milioni ons su una lista di 10 articoli [facendo così 100 milioni di operazioni] ... una differenza di ~ 3 secondi non è quella che chiamerei "significativa", ma il tuo chilometraggio può variare)
Quindi vai con quello che pensi tu in grado di leggere meglio (io personalmente uso il metodo RemoveAll
)
Nota: come far crescere la tua lista (questo a soli 10 elementi), MethodB
(la foreach
quella che duplica l'elenco) sarà più lenta e le differenze sarà più alto, dal momento che la duplicazione dell'elenco sarà più costosa. Ad esempio, facendo una lista di 1.000 articoli (con la condizione di 500 anziché 5) e 100.000 iterazioni, rende MethodB
34 secondi, mentre entrambi gli altri vengono eseguiti in meno di 2 secondi sulla mia macchina.Quindi sì, sicuramente non utilizzare MethodB
:-)
Questo non significa che foreach
è meno efficiente di for
, significa solo che per l'utilizzo di foreach
per rimuovere gli elementi da un elenco, è necessario duplicare detto lista, e questo è costoso.
Questo altro metodo (utilizzando foreach
) dovrebbe essere di circa veloce come le for
o RemoveAll
metodi (si tratta di un piccolo po 'più lento nel mio profilazione -perché si assegna una nuova lista, ho figura-, ma praticamente trascurabile):
public static void MethodD()
{
var originalList = new List<int>(Enumerable.Range(1, 1000));
var list = new List<int>(originalList.Count);
foreach (var item in originalList)
{
if (item <= 500)
list.Add(item);
}
list.Capacity = list.Count;
}
Hai solo bisogno di invertire la condizione.
non sto suggerendo questo metodo, solo dimostrando che foreach
non è necessariamente più lento di for
"migliore" come in cosa? prestazione? memoria? leggibilità? – Jcl
'for' non è meno efficiente di' foreach'. E invece di un ciclo, puoi usare 'RemoveAll', che ha prestazioni ancora migliori: https://msdn.microsoft.com/en-us/library/wdka673a%28v=vs.110%29.aspx –
@Jcl 1 Migliore rendimento 2. Migliori pratiche di codifica –