Francesco Bonizzi
Francesco Bonizzi

Reputation: 5302

Do I have to implement a Dispose method in this kind of custom object?

First example

public class GameObject
{
    Vector2 position;
    Vector2 scale;
    Color color;
    Texture2D atlas_reference;
    Rectangle source_rectangle;

    public GameObject()
    {
        //...
        // atlas_reference is a reference to the texture loaded in "LoadContent" in the main XNA's
        // loop
    }

    // ...
    // ...
    // ...

    public void Update(GameTime dt)
    { 
        //...
    }

    public void Draw(SpriteBatch spritebatch)
    { 
        //...
    }
}

Should I implement a Dispose method?

public void Dispose()
{
    atlas_reference.Dispose(); // ?
}

I think no because I would have put the method where it is loaded. Here, in this class, it just gets a reference. Am I wrong? Maybe I just need to do: atlas_reference = null; ?

Second example

public class GameWorld
{
    List<GameObject> game_objects;
    const int obj_number = 1000;

    public GameWorld()
    {
        //...

        for (int i = 0; i < 1000; ++i)
            game_objects[i] = new GameObject(); 

        // ...
    }

    // ...
    // ...
    // ...

    public void Update(GameTime dt)
    { 
        //... loop through the list and update every one
    }

    public void Draw(SpriteBatch spritebatch)
    { 
        //... loop through the list and draw every one
    }
}

Here I think I should implement Dispose because I am generating some object, so:

public void Dispose()
{
    for (int i = obj_number; i >= 0; --i)
        game_objects[i].Dispose();
}

But I know that GameObject's dispose method doesn't dispose anything, so should I implement it anyway?

What's the correct thing to do?

Upvotes: 0

Views: 312

Answers (3)

Cole Campbell
Cole Campbell

Reputation: 4857

Say you and I are good friends, and one day you come to me and ask to borrow my lawnmower. Of course I agree; you're my friend, after all, and I expect you to treat my property with the appropriate respect.

A few days later I need to mow my lawn, so I come over to your house and ask you to return my lawnmower. "Sorry," you say, "I can't."

"Why not?" I ask.

"Well, I took it out back behind the shed and set it on fire."

This is what you are proposing in your first example. You're loading asset_reference in your Game object, presumably through its content manager. In XNA, the content manager owns the assets it loads. It stores them in an internal cache so that it doesn't have to reload them every time you ask for them. So if you do this:

var resource = content.Load<Foo>("bar").Baz();
resource.Dispose();
content.Load<Foo>("bar").Baz();

The second call to Baz() is almost certainly going to throw an ObjectDisposedException! You're trying to mow your lawn with the burnt-out lawnmower that your crazy neighbor left behind.

Objects should manage the lifetimes of resources that they own. In the same way that you have no right to torch my lawnmower, another class has no right to torch the resources it's been given unless you explicitly transfer ownership of the resource.

The second example is closer to what I would consider proper--an object is disposing the resources that it created and therefore owns--but if you know that the Dispose() method on GameObject doesn't do anything, then why does it implement IDisposable at all?

Upvotes: 2

Oliver Salzburg
Oliver Salzburg

Reputation: 22099

As far as I understand, if your class contains members which are IDisposable, you should also make your class implement IDisposable and call Dispose() on all disposable members in your classes Dispose() method.

Upvotes: 1

BradleyDotNET
BradleyDotNET

Reputation: 61369

According to MSDN you only need to implement IDisposable to release unmanaged resources. XNA takes care of the content pipeline, so you don't need to worry about your Texture2D.

The reference(s) held by your object will be nulled on destruction, so you don't need to worry about that either. C# uses a reference counted garbage collector, so once the count reaches 0 it will automatically be collected.

To quote it directly:

You should implement IDisposable only if your type uses unmanaged resources directly.

Upvotes: 2

Related Questions