In the “C# reflection overhead” document, it is mentioned that Unity doesn’t garbage collect memory objects generated by reflection, but no further details are provided.
Is there a more detailed article on this mechanism?
I also have a few questions:
If I call obj.GetType().GetFields() multiple times on the same object, will each call generate new objects that won’t be garbage collected, or will this only happen on the first call?
Can objects created using Activator.CreateInstance() be normally garbage collected?
I understand this to mean that Type, MethodInfo or FieldInfo instances are cached. Calling GetFields() the first time will create and cache those objects and later calls will return the same instances. This only applies to the reflection metadata objects, Activator.CreateInstance() creates regular objects that will be garbage collected normally.
If you use reflection selectively, this won’t be much of a problem. However, if you have code that iterates all types and all their members (e.g. looking for attributes), then this can create a considerable amount of objects that will never be collected and put strain on the garbage collector.
This is why Unity itself e.g. creates RuntimeInitializeOnLoads.json during the build process, so that the player doesn’t have to iterate all types and methods to find the methods using the RuntimeInitializeOnLoad attributes.
Possibly, and it will certainly be inefficient as any repeat calls or property accesses are repeated.
It’s generally best practice to cache return values in local variables, be it via reflection:
var theFields = obj.GetType().GetFields();
Or typical game code:
var childComponents = GetComponentsInChildren<TheComp>();
Not just because it wastes time and energy, but primarily because it makes the code easier to read and debug!
Sure. It’s no different from new TheObject(); since all C# objects that are created are garbage collected. There is no way you can create an instance of a class that isn’t garbage collected.
Final consideration when using reflection: it will affect whether or how much you can tune the Player Setting called Managed Code Stripping. Without code stripping the executable can be noticably larger. But code stripping cannot consider runtime reflection. So if code stripping determines that a method is unused but you actually do call it but only via reflection, then the build will crash at the point of making that call with a high code stripping setting.
Lastly, I hope you’re not looking into reflection to make a dynamic system or generally to use it at runtime OTHER than reaching out for code that you do not have control over and there’s absolutely, definitely no other way of doing the task. For instance, I used reflection to be able to hook into the internal NetworkManager event “OnSingletonCreated” (or similar). That’s an acceptable use for reflection, but I also sent a feature request to make the event public. Bad use would be to read fields of your own classes, or to create a dynamic inventory, skill, etc game system.