Are Unity game objects managed or unmanaged resources? - c#

I have a class which instantiates a few unity game objects in a scene hierarchy. This class implements IDisposable. Should I handle these game objects as they were managed or unmanaged resources?
I am following the Dispose pattern, so where should I put calls like GameObject.Destroy(myGameObject)?
Thank you
Edit:
Ok, lets say I want to destroy the game objects instantiated by this class when it goes out of scope. How would you proceed then?
Edit 2:
I was testing the dispose. And I have found a solution. It doesnt work automatically, because GameObject.Destroy(myGameObject) cant be called from different thread. It will throw an error CompareBaseObjectsInternal. So, when no longer needed I call myClass.Dispose(). Also it seems irrelevant whether I handle Unity GameObject as managed or unmanaged.
myMain()
{
DisposeTestClass test = new DisposeTestClass();
//...
test.Dispose();
}
class DisposeTestClass : System.IDisposable
{
public GameObject uselessGameobject { get; private set; }
public DisposeTestClass()
{
uselessGameobject = new GameObject("Useless gameobject");
}
#region IDisposable
private bool _disposed;
~DisposeTestClass()
{
Debug.Log("~DisposeTestClass()");
this.Dispose(false);
}
public void Dispose()
{
Debug.Log("Dispose()");
this.Dispose(true);
System.GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
Debug.Log("Dispose(bool)");
if(_disposed)
{
Debug.Log("Disposed. Return.");
return;
}
if(disposing)
{
Debug.Log("Disposing of managed resources...");
// clean up managed resources
/*
if(uselessGameobject != null)
{
GameObject.Destroy(uselessGameobject);
Debug.Log("Game object destroyed.");
}
else
{
Debug.Log("Game object is null.");
}*/
}
Debug.Log("Cleaning up unmanaged resources...");
// clean up unmanaged resources
if(uselessGameobject != null)
{
GameObject.Destroy(uselessGameobject);
Debug.Log("Game object destroyed.");
}
else
{
Debug.Log("Game object is null.");
}
// set the flag
Debug.Log("Setting the disposed flag.");
this._disposed = true;
}
#endregion
}
}

No, you shouldn't implement IDisposable. But you can :).
"so where should I put call GameObject.Destroy(myGameObject)" And when you want your objects to be destroyed? Actually that doesn't matter whether you call myContainer.Dispose() or GameObject.Destroy(gObj).
The only reason to implement IDisposable for you is to write "convient" code like:
using(var container = new MyContainer())
using(var somethingElse = new MyObject())
{
\\Logic for container and somethingElse
}
But in Unity this makes no sense. I can hardly imagine case when in an Update GameObjects are created and then destroyed.

Huh, I think you slightly misunderstood what IDisposable and using statement is used for. You shouldn't implement IDisposable everywhere just to get rid of an object - this is garbage collector role, it knows better when an object shoyld be disposed.
IDisposable and using statement are used as a try/finally statement(of course it is much more complicated under the hood) and ensure that an object is removed/resolved right after it is not used anymore. It is not always a managed/unmanaged resource issue.
Using using statement won't ensure that your game object will be disposed. It all depends on the fact whether there are another objects pointing to it. Since it looks like a root object, I believe it will be held as long as possible by GC. Note that even if GC call Dispose() on your object, as long as it is referenced, it will be stay on the special queue until it is released.
On the other hand if your GameObject is less the Game, more the Object, you shouldn't consider disposing it using IDisposable as long as it is not somehow connected with some connection/file/external resource. GC will claim memory as soon as your object is considered garbage. Just take into consideration, that IDisposable is something which CLR treats a bit different and is not always the way to go.
EDIT
According to your question from edit - basically when a objects goes out of scope, you do nothing - if GC considers it garbage, it will be removed with the closest GC collection that occur. That's why C# is considered managed language and why you do not release memory on your own.

Related

Problems with managing shared ownership of IDisposable objects

[There is a similar question Shared ownership of IDisposable objects in C# but the accepted answer suffers from similar design problems which my solution has]
I have been trying to think around this problem having seen many designs taking a blind leap of faith in garbage collector when working in c#. Reason being many times its easy to ignore that one need to handle the IDisposable rather carefully making them close equivalent of resource allocation in c++. I understand that pedantically speaking Dispose is not the equivalent of c++ destructor but if you are holding on to native resources which needs to be cleaned in a deterministic manner it becomes very similar.
But if the object is shared by multiple resources (for eg. an HttpClient object which is meant to be created and used concurrently for performance), who owns the responsibility of calling Dispose since there is no single owner? To solve this problem I came up with a SharedOwner library which has a similar interface as shared_ptr.
Code snippet:
SharedOwner:
public static SharedHandle<T> MakeSharedHandle(Func<T> createSharedOwner)
{
var obj = new SharedHandle<T>(createSharedOwner());
return obj;
}
public SharedHandle(T obj)
{
AddReference();
m_object = obj;
}
public Handle<T> GetHandle()
{
AddReference();
return new Handle<T>(this);
}
internal void Decrement()
{
if (Interlocked.Decrement(ref m_refCounter) == 0)
{
m_object.Dispose();
m_object = default(T);
}
}
internal T GetInternalHandler() { return m_object; }
private void AddReference()
{
Interlocked.Increment(ref m_refCounter);
}
~SharedHandle()
{
m_object.Dispose();
}
Handle
is a transparent wrapper that manages the ref counting calls keeping that abstracted from consumers.
public sealed class Handle<T> : IDisposable where T : IDisposable
{
private SharedHandle<T> m_handle;
bool disposed = false;
internal Handle(SharedHandle<T> handle) { m_handle = handle; }
public void Dispose()
{
if (!disposed)
{
m_handle.Decrement();
GC.SuppressFinalize(this);
disposed = true;
}
}
~Handle()
{
if (!disposed)
{
m_handle.Decrement();
}
}
The typical usage pattern that I imagined would be:
using (var sharedClient = this.m_sharedClient.GetHandle()) // m_sharedClient is the SharedHandle passed
{
var httpClient = (HttpClient)sharedClient;
// use httpClient
}
Now I see two issues with this approach which deviate it from the original motivation of simulating shared_ptr behavior:
The first reference is held by SharedHandle itself. So even when all Handles are out of scope one reference would still be held by SharedHandle thereby making the if block in Decrement unreachable.
The final Dispose happens when the SharedHandle dies which in lot of sense is no better than not calling Dispose on the underlying object itself. Hence making the solution much less valuable.
I am thinking of moving the reference counting to Handle and using SharedHandle as the control block in shared_ptr but then that means that one may end up with a valid SharedHandle object holding on to a Disposed internal object.
Another alternative that I can think of is making SharedHandle derive from IDisposable and just call Decrement in Dispose. But then this brings other set of design issues. Is there anything that can be done to solve this problem in a more elegant way?

What happens if an object is "rereferenced" in it's finalizer?

Appearently, in java; "the object will not be collected until it gets unreachable again" (What if a finalizer makes an object reachable?). I assume the same holds in C#, but does it?
A quick example:
public static void MyWeakCache
{
private static readonly ICollection<WeakReference<MyFinalizableObject>> cache;
private static readonly IList<MyFinalizableObject> pendingRemoval;
// Other implementation
public static void Register(MyFinalizableObject myObj)
{
cache.Add(new WeakReference<MyFinalizableObject>(myObj));
}
public static void Deregister(MyFinalizableObject myObj)
{
pendingRemoval.Add(myObj);
}
}
public class MyFinalizableObject
{
public MyFinalizableObject()
{
MyWeakCache.Register(this);
}
~MyFinalizableObject()
{
// Object is reachable again after this call.
MyWeakCache.Deregister(this);
}
}
If the finalizer creates a new reference to the object then the object is not garbage collected. But there's no way of knowing when the finalizer will run or if it will run.
That creates a scenario where, for an unknowable period of time between when the last reference to the object is removed and when the finalizer is called, the object is in limbo, sitting in memory with no references to it. The natural flow of garbage collection is that no object should return from this state. It's like bringing Frankenstein to life. He's dead, let nature take its course.
It's interesting but has no practical application because there's no reason to do this. By definition finalizers don't exist to maintain references to objects. The only thing it can accomplish is creating unpredictable behaviors and bugs.

How to dispose managed and unmanaged objects in C#?

all. I've never worked with destructors nor dispose, so this is new to me.
I have a task of doing a class that has destructor and dispose methods, and that has a UInt64 Id property that is auto-incremental, and a static Dictionary<UInt64,MyClass> that must reference by Id all live instances of MyClass.
After searching how to use them properly, this is what I ended up doing:
public class MyClass : IDisposable
{
private static Object Lock = new Object();
private static Dictionary<UInt64, MyClass> LiveInstances = new Dictionary<UInt64, MyClass>();
public UInt64 Id { get; private set; }
public MyClass()
{
lock (Lock)
{
var newId = IncrementalId();
if (newId == 0)
{
throw new ArgumentException("Reached MAX VAL");
}
Id = newId;
LiveInstances.Add(Id, this);
}
}
~MyClass()
{
CleanUpNativeResources();
}
public void Dispose()
{
lock (Lock)
{
CleanUpManagedResources();
CleanUpNativeResources();
GC.SuppressFinalize(this);
}
}
protected virtual void CleanUpManagedResources()
{
LiveInstances.Remove(Id);
}
protected virtual void CleanUpNativeResources()
{
}
private static UInt64 IncrementalId()
{
for (ulong i = 0; i <= Convert.ToUInt64(LiveInstances.Count) ; i++)
{
if (i != UInt64.MaxValue && !LiveInstances.ContainsKey(i + 1))
{
return i+1;
}
}
return 0;
}
}
Now, my question is How do I dispose objects? Whether I try to find examples of disposing objects, I find something like this:
// Code to dispose the managed resources of the class
Console.WriteLine("Object disposed");
Thanks in advance.
Managed resources will be disposed automatically by the garbage collector at some point of time. Unmanaged resources are things like Filehandles, obtained by making a Windows API call that returns a Windows Handle which must be freed manually. You dont have anything which requires manual disposal.
If you don't free those handles, they will remain allocated for the duration of the program, but all .Net classes that have an unmanaged resource provide a Finalizer (see below) to make sure that they will normally be freed at some point.
(But if you were writing your own file handling class and forgot to free the file handle anywhere at all, the file would remain open until your program exited.)
Normally such unmanaged resources will be freed in two places:
The Dispose() method. This should be the normal way that you dispose unmanaged resources.
The Finalizer. This is a last-resort mechanism. If a class has a finalizer it will be called by the Garbage Collector when it cleans up a dead object. Any class which has an unmanaged resource should have a finalizer to clean up if the programmer forgets to call Dispose().
The basic Dispose pattern used goes something like this:
class MyObject : IDisposable
{
//indicates if dispose has already been called
//private bool _disposed = false;
//Finalize method for the object, will call Dispose for us
//to clean up the resources if the user has not called it
~MyObject()
{
//Indicate that the GC called Dispose, not the user
Dispose(false);
}
//This is the public method, it will HOPEFULLY but
//not always be called by users of the class
public void Dispose()
{
//indicate this was NOT called by the Garbage collector
Dispose(true);
//Now we have disposed of all our resources, the GC does not
//need to do anything, stop the finalizer being called
GC.SupressFinalize(this);
}
private void Dispose(bool disposing)
{
//Check to see if we have already disposed the object
//this is necessary because we should be able to call
//Dispose multiple times without throwing an error
if (!disposed)
{
if (disposing)
{
//clean up managed resources
components.Dispose();
}
//clear up any unmanaged resources - this is safe to
//put outside the disposing check because if the user
//called dispose we want to also clean up unmanaged
//resources, if the GC called Dispose then we only
//want to clean up managed resources
}
}
}

Deallocation of resources when using static members

Consider situation when we have a class with couple of static methods that use one static object.
public class Person
{
private static PresonActions actions = new PresonActions();
public static void Walk()
{
actions.Walk();
}
}
I know that the life cycle of static members in asp.net apps is equals to appdomain life cycle.
So this means that the object is not destroyed and the resources are not deallocated until I'll restart the appdomain.
But if we will use a property to create an instance of class PresonActions each time something access it, will the object will be destroyed or not?
public class Person
{
private static PresonActions actions { get { return new PresonActions(); } }
public static void Walk()
{
actions.Walk();
}
}
thanks.
Static variable continuouse allocation is an Evil. Keep an eye on your memory consuption, especially if you are talking about server side component (ASP.NET).
To answer your question: GC collects when he can an object which none longer reference by anyone in application.
Do not do this. It's very easy jump into memory problems with this approach and after spend hours to profile and find memory leaks.
If you want to change an object content, write a function that updates object content, without creating a new instance of it.
In your second code example, the garbage collector will destroy the object some time after the call to actions.Walk(). The garbage collector does this in a non-deterministic fashion, i.e. you cannot determine when it will perform this operation.
If your type is using resources which you want to dispose of deterministically, then the type should implement IDisposable and it's implementation of the Dispose method should perform the disposal of those resources.
Consuming code can then either call this method directly or use a using block to dispose of the object which in turn disposes of it's resources.
e.g.:-
public class PresonActions : IDisposable
{
...
public void Dispose()
{
...
}
}
public class Person
{
public static void Walk()
{
using(var actions = new PresonActions())
{
actions.Walk();
}
}
}
Note that, since you are not using the instance for more than one method call, there is no point creating it in a static property. It can be created it within the method, which allows use of a using block.

C# - Design-related dispose question (take two)

I asked a question earlier today, but I think I need to approach it in a different way (on top of that there was a "hang up" in regards to DataSet).
Here's a class that encapsulates the creation of a Font (in other words, it is reading data from an xml file and is creating a font, at runtime, based on what it reads from that file):
public class FontCreator
{
private Font m_TheFont = null;
public FontCreator( ... some parameters ... )
{
m_TheFont = GetTheFont();
}
public Font TheFont
{
return m_TheFont;
}
private Font GetTheFont()
{
// code, and more code, that eventually leads to:
Font f = new Font(fntFamily, fntSize, fntStyle);
return f;
}
}
The consumer of the FontCreator class looks something like:
public class TheConsumer()
{
private FontCreator m_FontCreator = null;
public TheConsumer()
{
m_FontCreator = new m_FontCreator( ... some parameters ... );
Initialize();
}
private void Initialize()
{
InitializeThis();
InitializeThat();
}
private void InitializeThis()
{
.... some code ...
SomeObject.ApplyFont(m_FontCreator.TheFont);
}
private void InitializeThat()
{
... some code ...
SomeObject.ApplyFont(m_FontCreator.TheFont);
}
}
What code do you add, and where, to ensure that "TheFont"'s Dispose method is explicitly called?
If you don't wish to maintain a reference to TheFont after it is initially used, then call it's Dispose method in your constructor, right after Initialize. If you wish to keep TheConsumer alive for a while and maintain a reference to TheFont, it gets more interesting. Two Options:
You can have TheFont's dispose method called from the Destructor of the TheConsumer object. This is not the common practice and has problems. Mainly, this is not called until garbage collection happens. Better is:
You can make the TheConsumer object itself implement IDisposable, and call TheFont.Dispose from TheConsumer.Dispose. Since TheConsumer implements IDisposable, the code that uses it should call its Dispose method.
Edit in response to harsh comment!
Yes, I should have made clear to only use 1 in addition to 2, if at all. I know all developers everywhere are supposed to notice when IDisposable is implemented, but they often don't. If the referenced managed resource might really remain around a long time and cause problems if not properly disposed, I sometimes have a safety Dispose() method call in the destructor of the object holding the reference. Is that so wrong? :)
public TheConsumer()
{
using (m_FontCreator = new m_FontCreator( ... some parameters ... ))
{
Initialize();
}
}
I am confused, if you want to quickly use the font creater object then implement IDisposable on the FontCreater and use
using(m_FontCreator = new FontCreater(....))
{
InitializeThis();
InitializeThat();
}
If you need to keep the instance of the FontCreater through the lifetime of TheConsumer, then implement IDisposable on both FontCreater and TheConsumer classes.
public class TheConsumer : IDisposable
{
void Dispose()
{
if(m_FontCreator != null)
m_FontCreator.Dispose();
}
}
then use TheConsumer class like so
using(TheConsumer consumer = new TheConsumer(....))
{
....
}
Answer 1: Avoid it. Don't keep objectsthat contain unmanaged resources around any longer than necessary.
Answer 2: If you do need the embedded fields as shown in your code, than both the FontCreator and the Consumer class need to implement IDisposable. But not a destructor (Finalizer).
The main argument for this is that FontCreator is the 'owner' of the Font and should therefore take responsibility. And the Consumer is responsible for the Creator in the same way.
As others have noted, it appears you can at least avoid the m_FontCreator field in the Consumer class. But it depends on the rest of the code, is m_FontCreator used elsewhere?

Categories

Resources