2015-12-20 9 views
10

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.

+0

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

+0

@dasblinkenlight abbastanza giusto, teniamolo aperto allora. –

risposta

11

Il motivo lambda non è GC-ed è la struttura del lambda stessa:

item => item > 5000 && item < 7000 

Questo lambda non lo fa cattura nulla, il che significa che può essere compilato una sola volta, e riutilizzato per sempre. C# lo scopre, e sfrutta i lambda in modo simile memorizzandoli staticamente per migliorare le prestazioni.

Se il tuo lambda avesse catturato una variabile dal suo contesto, sarebbe stata raccolta dalla spazzatura quando non è più necessaria.

Vedere this answer per ulteriori informazioni sulla durata lambda in. NET.

+0

Perfetto, quello e le risposte collegate spiegano tutto. –

Problemi correlati