- Home /
How to get a reference to the owner-Script from inside a Class which is being used as field/property
Hello. I am creating a class - lets call it Foo ( not Monobehaviour ) which then will be used on Monobehaviours - lets call them Bar - as a field/ or Property. Is it possible to somehow get a reference from Foo to Bar ? Maybe with reflection or something like that ?
Particularly, I would like to keep a static list/ Set of Monobehaviours inside Foo which is a collection of all Monobehaviours which do use Foo somewhere on some of their Scripts.
Thank you in advance for any answers.
Answer by JVene · Jul 22, 2018 at 11:47 PM
There is no automatic means, no reflection service to ask for the owner of the references. You have to build that yourself. The initialization of a new Foo, for example, could take a reference to the "this" of Bar when the Foo is allocated, and store it. Foo would "know" the Bar that owns it. Similarly, a static registry can be built (a container) of all the Foos that Bars have, but nothing does that automatically.
However, you have to be mindful of potential circular references with this kind of design. If Bar uses a reference to own a Foo, and Foo has a reference to the Bar, who let's go first?
Circular references also have a compile time meaning, where one class requires the other, and the reverse at the same time. This should be avoided in the first place, and there are almost always better design choices that avoid this. You can get into that mess because you start down that road.
However, the circular reference I'm talking about is about storage, not compilation dependency.
References in C# are reference counted smart pointers under the hood. This allows several objects to consume a common Foo without concern for who is last to hold that Foo (the reference counter deals with that for you). The problem comes when that Foo also hold such a reference to the Bar. The Bar is owned by someone if it is instantiated (not a purely static class). As such, something has a reference to the Bar (as a MonoBehaviour derivative, it is owned by the Unity framework through some reference that holds it). If Unity clears all content, the Bar is expected to disappear, but the Foo that is holding it keeps holding it, and the Bar, holding that Foo, has not explicitly let go of the Foo - they are holding each other, the definition of circular reference in this context.
They will "float away", bonded to each other, but nothing else in code will have reference to them. This is a memory leak, by design.
Some mechanism has to exist to break such a tie, or the design fails.
We have to ask, then why create a circular reference. They are nuisance to such an extent that when they occur it brings into question what design caused it. Why is it important enough to have the circular reference that any machinations should be expended to carefully break the circular reference at the appropriate time?
There are design patterns specifically aimed at dealing with this, but unfortunately C# doesn't directly employ some of them. In C++, for example, the shared_ptr has a weak_ptr counterpart which is used precisely for this circumstance. I don't know of a counterpart in C#.
You can simply ensure that one breaks before the other. When Bar is shut down, it can explicitly remove the Foo while clearing Foo's reference to the Bar, managing the problem.
C# is not particularly strong on this point because it lacks a deterministic destructor, and therefore can't participate in RAII designs where this connection or shutdown of an object should occur at a specific, determined moment (like destruction).
You can look into finalize, and it can "do" in a pinch, but it isn't guaranteed to execute at the moment Bar is actually done with Foo. It happens when GC gets around to clearing Bar out of memory.
Thank you very much for that indepth explenation. Definitely a fiew new pieces of wisdom you brought to me here. Hope this exhaustive answer will help others too. I found a solution now without circular references for my problem. Not as elegant as it would have been with weak references , but good enough. Thank you very much.
Your answer
![](https://koobas.hobune.stream/wayback/20220612171250im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Monobehavior vs other classes? 1 Answer
How to structure code for squad selection and movement 0 Answers
Classes : extend MonoBehaviour issues 1 Answer
Accessing Monobehaviour classes on other objects 1 Answer
Unity problems with classes C# 1 Answer