It is well known in .NET that types are not garbage collected, which means that if you\'re playing around with f.ex. Reflection.Emit, you have to be careful to unload AppDom
To answer your first question:
Generic constructions of types are not collected.
However, if you construct C<string>
and C<object>
, the CLR actually generates the code for the methods only once; since reference to string and reference to object are guaranteed to be the same size, it can do so safely. It's pretty clever. If you construct C<int>
and C<double>
though, the code for the methods gets generated twice, once for each construction. (Assuming that the code for the methods is generated at all of course; methods are jitted on demand; that's why its called jitting.)
To demonstrate that generic types are not collected, instead create a generic type
class C<T> { public static readonly T Big = new T[10000]; }
C<object>
and C<string>
share any code generated for the methods, but each one gets its own static fields, and those fields will live forever. The more types you construct, the more memory will be filled up with those big arrays.
And now you know why those types cannot be collected; we have no way of knowing if someone is going to try to access a member of one of those arrays at any time in the future. Since we don't know when the last array access is going to be, they have to live forever, and therefore the type that contains it has to live forever too.
To answer your second question: Is there a way to make dynamically-emitted assemblies that are collected?
Yes. The documentation is here:
http://msdn.microsoft.com/en-us/library/dd554932.aspx
Irrelevant to code sharing or code not sharing, each MakeGenericType attempt will create new internal CLR classes for metada which will consume memory. Type objects are created directly in CLR code (not in managed code), there exists only one instance per Type object, so you can compare them for reference equality. CLR itself holds a reference to it so they cant be GC'ed but in my tests i confirmed GC can move them.
Edit: Reference hold by CLR could be weak reference so after digging RuntimeTypeHandle.cs source i see
internal bool IsCollectible()
{
return RuntimeTypeHandle.IsCollectible(GetTypeHandleInternal());
}
which is most probably false, considering Eric Lippert