Stavo osservando l'impatto della memoria di una semplice query LINQ e ho notato che la query LINQ creava 2 oggetti extra di tipi Enumerable+WhereListIterator<Int32>
e Func<Int32, Boolean>
.Perché un GC dopo una query LINQ libera il WhereListIterator ma non il Func che rappresenta la condizione?
Il codice utilizzato è questo:
static void Main(string[] args)
{
// Setting baseline snapshot
var list1 = new List<int> { 4862, 6541, 7841 };
var list2 = new List<int>(list1.Count);
var list3 = new List<int>(list1.Count);
// First snapshot: LINQ usage
list2.AddRange(list1.Where(item => item > 5000 && item < 7000));
// Second snapshot: foreach-loop
foreach (var item in list1)
{
if (item > 5000 && item < 7000)
{
list3.Add(item);
}
}
// End gather
Console.Read();
}
Al istantanea dopo l'foreach
ciclo mi accorgo che l'oggetto Enumerable+WhereListIterator<Int32>
è garbage collection, ma il Func<Int32, Boolean>
è ancora in memoria.
Perché questo è ancora tenuto in giro? In quel momento (all'istruzione Console.Read
) non penso che nulla stia ancora facendo riferimento a esso e un GC è stato forzato dal profiler (che è il motivo per cui l'iteratore viene raccolto).
Nota: la raccolta di istantanee aggiuntive non modifica il numero di oggetti liberati, pertanto non è questione di contrassegnare lo Func
per la raccolta successiva.
Commento sulla riapertura della domanda: sebbene la domanda collegata sia sicuramente correlata, questa domanda si pone in merito a un caso specifico e fornisce una dimostrazione per dimostrare cosa sta succedendo. – dasblinkenlight
@dasblinkenlight abbastanza giusto, teniamolo aperto allora. –