Search code examples
c#inheritancestatic-variables

Automatically create a copy of a static variable for each derived class


I have a base class with a static variable. I want to create derived subclasses which will automatically have their own unshared static variable. Ideally it would look like this:

class Parent
{
     Texture2D picture;
     static Texture2D pictureOrigin;

     Parent()
     {
         picture = pictureOrigin;
         /*Loading the static origin to an instance variable
         because I might want to have more pictureOrigins 
         and alternate them or perhaps change the picture
         of the instance based on a certain event, etc.*/            
     }
}

class Subclass1 : Parent
{
    Subclass1() : base()
    { }
}

class Subclass2 : Parent
{
    Subclass2() : base()
    { }
}

void main()
{
    Parent.pictureOrigin = Load("pictureForParent"); 
    Subclass1.pictureOrigin = Load("pictureForSubclass1");
    Subclass2.pictureOrigin = Load("pictureForSubclass2");
    //Then creating instances of the classes and drawing them, etc.
}

But what happens is that they all get the last loaded image (pictureForSubclass2) because the static variable pictureOrigin is shared between them.

The quickest fix is manually adding new static variable pictureOrigin to each subclass and hiding the pictureOrigin variable of the base class:

class Subclass1 : Parent
{
    new static Texture2D pictureOrigin;

    Subclass1() : base()
    {
         picture = pictureOrigin;
    }
}

Alternatively, creating abstract methods or similar to ensure the creation of the new static variable in the subclasses. But it seems like too much of a hassle and not too elegant. Is there a better way of doing this?


Solution

  • Your question smells like a poor design. Static variables are generally poor practice in my opinion, and proper object-oriented design can eliminate the need to ever use static members.

    Try refactoring like so:

    public class Parent
    {
        private Texture2D texture;
    
        public Parent(Texture2D texture) {
            this.texture = texture;
        }
    
        public Texture2D Picture { get {
                return texture;
            }
        }
    }
    
    public class SubClass1 : Parent
    {
        public SubClass1(Texture2D texture) : base(texture) {
    
        }
    }
    

    Let me elaborate on why static is a poor choice:

    1. Your class is now only good for a single bitmap. Eliminates the possibility to reuse a class for several bitmaps (this is the limitation you're fighting against)
    2. Your class is not in a valid state until the static setter is called. Generally objects, once constructed, should be in a valid state. It won't be obvious to others if they're using your object that they have to statically set the bitmap on the class.
    3. Breaks the natural garbage collection. For example if you wanted the Texture2D object to be garbage collected when all the instances of SubClass are collected it wouldn't work with your static design. Alternatively, if you use a oop design (like suggested) you have the flexibility to garbage collect or not depending on your use cases.
    4. Makes threading more complicated. Statics are global, so you need global mutexes to guarantee thread-safety.
    5. Makes testing more difficult. If you want to unit test the class, you have to make sure that the static is cleaned up after every test, and you couldn't run two unit tests against this class in parallel.
    6. Makes memory management inflexible. If you use object-oriented design you can choose to share bitmaps among all instances, or allocate a new bitmap for every instance.