Static contrustors, destructors, and members.

wyrd

Senior Contributor
Joined
Aug 23, 2002
Messages
1,405
Location
California
(Using C#)

Okay.. static constructors are guaranteed to run sometime before the class is instantiated or called (ie; static method) for the first time, right? Also.. can you make a static destructor? ie; The destructor is guaranteed to run sometime after all instantiated classes are run through the GC (or when the program closes).

I was thinking of encapsulating an imagine inside a class, but every time I create the class I don't want the same image to be loaded over and over again (waste of memory). In short I was thinking of static members to handle this, so I only had a single image loaded that all classes shared.

Is this a good idea? It seems rather logical to me, however if static destructors aren't possible or static works in a different way other then what I described above (according to my understanding of it), I'll have to think of another way to handle this.
 
Easy answer: You can't have a static constructor or destructor :)

If you really need them around all the time, you can use internal, private, etc. static variables. Wrap them in a property that first checks if the variable is null and instantiates it and loads the image. On future calls to get the image the if will be false (image already loaded) and just return the image reference.

-Nerseus
 
Yes, you can have a static constructor.

No, you can't have a static destructor.

Is this static image member a managed resource? Your static destructor, if you could have such a thing, would, I guess, be called just before the class is unloaded -- which, I guess, would be just before the AppDomain is unloaded.

You could spend time thinking of a very clever solution to the problem you described above. However, if the answer to my "managed resource" question is yes, then you could just as easily say, "Who cares? The AppDomain is being unloaded anyway. Everything must go!" The image won't be around much longer, no matter what happens. Therefore, there is little point in you worrying about disposing of your image.

If it is an unmanaged resource, then, yes, you have a problem, because you need to clean up that image resource before the class/AppDomain is unloaded. In this case, I think you'd either have to do something with the AppDomain.DomainUnload event or write some sort of wrapper class for your unmanaged resource, with a Dispose() and a destructor, so that the resource would be released when the finalizer is run (just once, since it'd be a static reference to a single wrapper class instance).
 
However, if the answer to my "managed resource" question is yes, then you could just as easily say, "Who cares? The AppDomain is being unloaded anyway. Everything must go!" The image won't be around much longer, no matter what happens.

If the program is running a long time and I have several static members like this in various different classes, I don't want them all to have images sucking up memory when they're not in use. So in short, I would care, and so would the person running the program.
 
wyrd said:
If the program is running a long time and I have several static members like this in various different classes, I don't want them all to have images sucking up memory when they're not in use. So in short, I would care, and so would the person running the program.

Well, OK, but that's a different concern from the one originally voiced. If you're concerned about the memory usage of your several static members while the program is running (and not just about releasing those resources when the class goes away), then the first solution that comes to mind is this:

Reference the resource via a static WeakReference member. Implement a private GetImage() method or whatever. If the resource has been collected by the GC, then you'll have to recreate it. If it's still hanging around, then fine: the system obviously didn't require that memory just yet.
 
_SBradley_ said:
Well, OK, but that's a different concern from the one originally voiced. If you're concerned about the memory usage of your several static members while the program is running (and not just about releasing those resources when the class goes away), then the first solution that comes to mind is this:

Reference the resource via a static WeakReference member. Implement a private GetImage() method or whatever. If the resource has been collected by the GC, then you'll have to recreate it. If it's still hanging around, then fine: the system obviously didn't require that memory just yet.

Maybe you misunderstood what I was saying (or I wasn't saying it clearly enough). I wasn't voicing a concern, I was looking for a way to handle the particular situation if static destructors weren't possible.

The weak reference is a good idea (I never thought about it). However it may cause some performance issues while the program is running (this is for a game). If for some reason the GC collects the image while the program is using the particular image, it could cause some serious and random performance issues to reload an image at that time.

I appreciate the ideas, but for now I'm going to just keep track of how many instances of the class are in use with a static counter (inc upon creation, dec upon destruction). This way I'll at least have minor control over when I want the image to be marked for disposal.
 
wyrd said:
I appreciate the ideas, but for now I'm going to just keep track of how many instances of the class are in use with a static counter (inc upon creation, dec upon destruction). This way I'll at least have minor control over when I want the image to be marked for disposal.

OK. Sounds like a plan. :) Yes, that gives you more control over when the image will be released, compared to our hypothetical static destructor, in that you can release the resource any time during the running of the program, rather than just when the class is unloaded (or the AppDomain goes away).

Good luck! ;)
 
That's exactly the way COM classes work. :) They keep a reference count, incrementing on initialize, decrementing on finalization.

Also, you needn't worry about the garbage collector; unless you mark an object for disposal with the Dispose method, the GC will only collect objects it is sure are not in use. Even when you do Dispose it, I'm not sure that GC will attempt collection until the object is finished.
 
I did some research into the static constructor... sorry about the mistake. Unfortunately, my test was using "public static Class2" instead of just "static Class2" - I didn't really read the error message, just assumed you couldn't have a static constructor.

The static constructor seems to work like Sub Main in a DLL in VB6. It only gets called once and only when you first create an instance of the class. So if you have two constructors, one static one not, the static one gets called first then the non-static one. Even when all instances of the class are disposed and collected and then a new instance is created, only the non-static constructor is called.

Hope that helps :)

As for the original problem, for the most part I wouldn't worry about the cleaning up of the objects as far as performance is concerned. You're going to load bitmaps for a game so just load them. As Volte said, as long as there is a reference to the object the GC will not collect it. When you're truly done with the reference, you'll have to clear it (use Dispose followed by setting the variable to null). Let the GC collect it when it's ready.

If you start loading more images and the system is running out of memory or handles, the GC will detect it and clear the unused images for you.

The only time I can think of that you wouldn't want the GC to run automatically (meaning you start handling some of the memory management yourself) is if you were doing a LOT of loading/unloading of images (or resources in general). If, for instance, you were loading a WAV file every time you wanted to play it. Since you're leaning towards loading the bitmaps once only, I wouldn't worry about the performance of the GC running.

-Nerseus
 
Hmm okay, perhaps there's some confusion as to what I'm looking to implement. Or worse yet, maybe I'm not understanding the suggestions.

I have a class for a game, we'll call it GenericMonster. The interface looks something like this;

- Get/Set Rectangle
- Get/Set MovementSpeed
- Get/Set Health
- Get/Set Alive
- Move(Direction d)
- Draw(Graphics g)
- Attack(Player p)
- Wound(int amount)

Keep in mind this is just a lame example to get my point across, don't be responding with "well your class needs such and such" unless it relates to what I'm about to explain. :P

Now, the program (the game) has to keep track of these GenericMonsters, which there can be 1,000's of. To keep in line with information hiding, encapsulation, and all that wonder OO stuff, the class GenericMonster is treated as a black box. The game does not need to be worried about the implementation. Because of this, it cannot be aware of what image(s) the GenericMonster is using to display itself when the game calls GenericMonster.Draw(g).

In short, the GenericMonster has to keep track of itself and needs to know when to Create and Dispose the image(s) it's using to display itself (and all other instances of it) when the GenericMonster.Draw() method is called.

This is how my implenentation idea to solve this would work (ignore errors if found, this is just an example of what I was thinking).

C#:
class GenericMonster {
   private static int _instances = 0;
   private static Bitmap _img = null;
   
   public GenericMonster() {
      if (_instances == 0) {
         _img = new Bitmap(); // Load image from source.
      }

      _instances++;
   }

   public ~GenericMonster() {
      _instances--;

      if (_instances == 0) {
         _img.Dispose();
         _img = null;
      }
   }
}

VF and Ners.. I understand the image will not go through the GC until there are no more references to it, but I still need to call Dispose somewhere. I was not implying a GC.Collect() in the slightest (which I know is a bad thing to be doing).

Because my game doesn't know about the inner workings of GenericMonster, I have to have some way of GenericMonster knowing about itself, so it can Dispose of the image it's using when it's no longer in use. Having my game know about what image GenericMonster is using, and explicitly Dispose of it would require the game to know about the inner workings of GenericMonster. As I explained above (with the way I'm implementing this), I do not want this to be the case.
 
Your example looks good to me, assuming that inheriting from that class into a new class will create a new set of static variable for that class, rather than just using the static variables of the parent class. In the latter case, it would throw the reference count way off... I think it will handle it properly though.
 
I've found that in some cases, one generic class for a game entity just won't work. For instance, I use a Ghost object to hold a ghost's data (in a Ms Pacman clone) - position, speed, state, AI, etc. - and a GhostUI class to handle the graphics portions. Splitting it apart means I can change the graphics easily without worrying about the "real" ghost. The graphics are, after all, just for display and having nothing really to do with a Ghost.

Having said that, the Ghost object DOES use the GhostUI for a few things, such as the size of the sprite (to calculate how close a Ghost can be to a wall before going through it).

I also have some manager type classes that do nothing but handle the graphics used by each class. For instance, I have all the sprites in one bitmap. I don't want a separate copy of the whole bitmap for each instance of GhostUI. The manager class really came about when I went to DirectX. The performance of having a separate texture per object and all the extra vertex buffers (rather than one large one) caused some performance issues. I was getting 20-30 FPS one a simple 480x640 (taller than wide) version of Ms Pacman with not a whole lot going on. I isolated it to the rendering and did some research, found out what worked for me and changed things.

The full details of the implementation aren't that important in themself. I only bring them up to point out that if you have your Data-related "stuff" in a class AND have the Graphics-related "stuff" in the same class, you may run into complications later when you try and change something. You can start with the cleanest code in the world, but one little problem may force you to rethink how all of your classes work and/or are structured. The key is to code some sample projects (prototypes) to be sure of how things work before really starting on your "final" version of the game. Many business apps don't need this prototype for speed or workability issues. They use screen prototypes to see if the design is good, but they usually don't do much. With a game, the prototype is all about "will this work" and not as much about how it looks.

-Nerseus
 
That looks pretty good. (You said to ignore errors in the code, so I won't mention the fact that you can't put access modifiers on destructors. ;))

As wyrd said previously, the advantage of this technique is that, say you had 'class Level1Boss : GenericMonster' and 'class Level2Boss : GenericMonster', which used two separate groups of images, you wouldn't have to keep all of Level1Boss' images around whilst level 2 was being played. :)

Come to think of it... If GenericMonster were your base class, and the Image/Bitmap references were to be static members of the monster classes, then you'd need something along the lines of:

protected abstract Image[] GetImages();

Otherwise, there is no (nice) way for GenericMonster to access the static members in the derived classes.
 
Last edited:
Nerseus:
Hmm, you make some valid points. I never thought about it quite that way. I originally planned on having some sort of GraphicsManager object and then having GenericMonster (as in my example above) reference the GraphicsManager and use it to extract info. needed. But I don't know, I couldn't thing of a way to implement it where it made sense (this is where my lack of experience hurts). Your GhostUI approach sounds interesting, maybe with time and some trial-and-error I'll come up with an approach that's similar.

For my Tetris wannabe game I have my blocks class which inherits from a rectangle class (which encapsulates the rectangle struct), and also inherits a shape interface. The shapes (L shape, I shape, etc.. the falling shapes) also inherit from rectangle and the shape interface, but the implementation is different (it controls an array of blocks).

I can't help but think perhaps I'm going about this the wrong way, but I suppose the only real way to learn is to make mistakes. So I'm going to stop thinking to much about the mechanics of the game and just try to FINISH it, then I can use the mistakes I made in this game to improve the design of the next one.

SBradley:
Yeah I know non-static methods can't access static methods directly, but I don't have to much experience with all this static stuff and I just needed to get my general idea across (I try to stay away from them as they seem to much like global variables to me)
 
Back
Top