I am making a Color class, and provide a standard constructor like
Color(int red, int green, int blue)
And then I want to provide an easy way to get the most common colors, like Color.Blue, Color.Red. I see two possible options:
public static readonly Color Red = new Color(255, 0, 0); public static Color Red { get { return new Color(255, 0, 0); } }
What I don’t fully understand is if there is an advantage of one over the other, and how exactly the static keyword works. My thoughts are: The first creates one instance, and then that instance stays in memory for the entire duration of the program, and every time Red is called, this instance is used. The latter only creates something when first used, but creates a new instance every time. If this is correct, then I would argue that if I supply a lot of predefined colors, then the first would use a lot of unnecessary memory? So it is memory usage vs the runtime overhead of instantiating an object every time I guess.
Is my reasoning correct? Any advice for best practices when designing classes and use of the static keyword would be great.
I’m guessing that you’re probably already aware that the framework provides a
Colorstruct. I’m guessing that you’re creating aColorclass just for practice.You expressed uncertainty about the meaning of the
statickeyword, although you’ve used it correctly. Whenstaticis applied to a member of a class or struct, it means that that member belongs to the class as a whole, and does not apply to individual instances. Static data members (fields) are created only once; instances do not get their own copies. Static functions (methods and properties) are called without an instance reference.As far as memory usage goes, I wouldn’t worry too much about it in your case. Your
Colorclass shouldn’t use more than a few bytes per instance (for instance, the framework’sColorstructure stores red, green, blue, and alpha in one 32-bitint.). If yourColoris a really aclassinstead of astruct, then you’ll have a few more bytes in overhead (each instance will have an additional 32-bit v-table/typeinfo pointer, and each reference is an additional 32-bits), but even so, you’re talking about 12 bytes or so per instance. If you have 100 different colors predefined, you’ll use <= 1200 bytes. Really no big deal.There are reasons for lazy-instantiation, though. There are classes that do use a lot of memory, and ones that hold on to limited system resources, and ones that take a long time to construct themselves, etc. For these classes it’s sometimes better to use a pattern like:
Another consideration is mutability. Is your
Colorclass mutable or immutable? In other words, can instances of your class have their value changed, or do they always, once created, represent the same value?If your
Coloris mutable, then the only correct way to have a static ‘Red’ accessor would be your second example, where you create a new one every access. That way someone can’t do something like:and make the single shared Color.Red instance actually represent yellow, instead.
But also keep in mind that in a case like:
A lot of instances of your
Colorclass are going to be created. They’ll be garbage collected later, of course, but this is still a case argument for your first construct above (or the ‘Heavy’ example I gave).Now if your
Coloris actually a struct, then it’s a slightly difference story. There’s no heap allocation when younewa struct, and there’s no v-table or reference pointer, so the real consideration is then just how long your constructor takes.