c# - Are MakeGenericType / generic types garbage collected? -


it known in .net types not garbage collected, means if you're playing around f.ex. reflection.emit, have careful unload appdomains , on... @ least that's how used understand how things work.

that made me wonder if generic types are garbage collected, more precise: generics created makegenerictype, let's say... example based on user input. :-)

so constructed following test case:

public interface irecursiveclass {     int calculate(); }  public class recursiveclass1<t> : irecursiveclass                                    t : irecursiveclass,new() {     public int calculate()     {         return new t().calculate() + 1;     } } public class recursiveclass2<t> : irecursiveclass                                   t : irecursiveclass,new() {     public int calculate()     {         return new t().calculate() + 2;     } }  public class tailclass : irecursiveclass {     public int calculate()     {         return 0;     } }  class recursivegenericstest {     public static int calculatefromuserinput(string str)     {         type tail = typeof(tailclass);         foreach (char c in str)         {             if (c == 0)             {                 tail = typeof(recursiveclass1<>).makegenerictype(tail);             }             else             {                 tail = typeof(recursiveclass2<>).makegenerictype(tail);             }         }         irecursiveclass cl = (irecursiveclass)activator.createinstance(tail);         return cl.calculate();     }      static long memoryusage     {                 {             gc.collect(gc.maxgeneration);             gc.waitforfullgccomplete();             return gc.gettotalmemory(true);         }     }      static void main(string[] args)     {         long start = memoryusage;          int total = 0;         (int = 0; < 1000000; ++i)         {             stringbuilder sb = new stringbuilder();             int j = i;             (int k = 0; k < 20; ++k) // fix recursion depth             {                 if ((j & 1) == 1)                 {                     sb.append('1');                 }                 else                 {                     sb.append('0');                 }                 j >>= 1;             }              total += calculatefromuserinput(sb.tostring());              if ((i % 10000) == 0)             {                 console.writeline("current memory usage @ {0}: {1}",                                    i, memoryusage - start);             }         }          console.writeline("done , total {0}", total);         console.writeline("current memory usage: {0}", memoryusage - start);          console.readline();     } } 

as can see, generic types defined 'possibly recursive', 'tail' class marks end of recursion. , ensure gc.totalmemoryusage isn't cheating, opened task manager.

so far good. next thing did fire beast , while waiting 'out of memory' ... noticed - contrary expectations - not consuming more memory on time. in fact, shows slight drop in memory consumption in time.

can please explain this? generic types collected gc? , if so... there reflection.emit cases garbage collected?

to answer first question:

generic constructions of types not collected.

however, if construct c<string> , c<object>, clr generates code methods once; since reference string , reference object guaranteed same size, can safely. it's pretty clever. if construct c<int> , c<double> though, code methods gets generated twice, once each construction. (assuming code methods generated @ of course; methods jitted on demand; that's why called jitting.)

to demonstrate generic types not collected, instead create generic type

class c<t> { public static readonly t big = new t[10000]; } 

c<object> , c<string> share code generated methods, each 1 gets own static fields, , fields live forever. more types construct, more memory filled big arrays.

and know why types cannot collected; have no way of knowing if going try access member of 1 of arrays @ time in future. since don't know when last array access going be, have live forever, , therefore type contains has live forever too.


to answer second question: there way make dynamically-emitted assemblies collected?

yes. documentation here:

http://msdn.microsoft.com/en-us/library/dd554932.aspx


Comments

Popular posts from this blog

Why does Ruby on Rails generate add a blank line to the end of a file? -

keyboard - Smiles and long press feature in Android -

node.js - Bad Request - node js ajax post -