Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Understanding lifespan of C# classes (non-MonoBehaviour)

Discussion in 'Scripting' started by FeastSC2, Mar 4, 2020.

  1. FeastSC2

    FeastSC2

    Joined:
    Sep 30, 2016
    Posts:
    870
    Many times in my project I avoided making standard C# classes (classes not inheriting from MonoBehaviour) because I have not found a way to easily get rid of them or to let the program know that this class should no longer be used and that it should point to null.

    Maybe it's because I misunderstand something...

    With a MonoBehaviour you can call Destroy() and it will make any references to this object point to null.

    With a standard C# class, you cannot call Destroy() meaning that as long as somewhere in the program there is a reference to the object, it won't get picked up by the garbage collector and it won't point to null.

    This means that should a script check to see if the object still lives with object != null, he will see that it lives.
    If I try and set the object = null, this will merely make the reference pointer point to null. Meaning that if there's another object that points to the object, the object will still live.

    In comparison to Unity's components where you can simply call Destroy(Component) and any scripts attempting to do something with the component will have a nullreference.
    I would like to know how to replicate this behaviour with standard C# classes.

    How can I destroy an instantiated standard C# class?
    Or am I thinking incorrectly about all of this?
     
  2. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,393
    Simply set all references to the object to null. Like in Unity, the garbage collector will do its magic once no object references it any more.

    You can also define a destructor that similar to OnDestoy is invoked. In that dstructor, release all memory you have allocated yourself.
     
  3. csofranz

    csofranz

    Joined:
    Apr 29, 2017
    Posts:
    1,393
    With regards to your question "how can I FORCE destuction of an object in C#', the answer is: you can't except when all referencing objects relinquish their reference. This is a central design decision in C#. The assumption is (and I find it quite sane), that objects know how long they want to retain an object, and therefore it makes no sense to destroy it before that point in time when all objects are done. That allows safe programming without null checks at every guard, switch or dereference.
     
  4. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    871
    Disclaimer: Someone more knowledgeable might come around to correct me, don't take this as gospel.
    This is not the entire truth, on the C# scripting end the object will live on as any old C# object does in wait for the garbage collector to clean it up. On the engine side of things all resources should be destroyed or unloaded.
    What you get if you try and access an Unity object that's been destroyed is a MissingReferenceException, not usually a NullReferenceException which you usually get from null references. There's also the UnassignedReferenceException which you get from inspector visible/serialized that's not been filled.
    You can see these differences in the inspector as well; None/Missing.
    Unity overrides several operators (bool, ==, !=) that make tests like foo==null return true if the object has had Destroy called on them, even if the C# object might still live.

    Regarding your original question, I don't know of another way than to implement something like this yourself, by turning all fields into properties and check some has-been-destroyed flag whenever you access them.
    There are some concepts like Disposable in .Net where you can control when and how garbage collections of a certain object works, but this may be complicating things more than what it's worth and may not be particularly usefull in everyday Unity use.
     
  5. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,479
    this isn't C++, you do not have to worry about manually managing what is in memory. Once all references to a object go out of scope or get nulled the object will be marked for GC and cleaned up in the future.

    if you want to manually close resources or remove things, you may want to look into the IDisposable interface, the Dispose method that it makes you implement and the using statement.

    its a good way to let you generically calling logic for tearing down a object, or in the case of the using statement a way to ensure Dispose properly gets called once you exit a scope.
     
unityunity