I sometimes write classes like this:
public class FpsText
: Text
{ private readonly MovingAverage _movingAverage
= new MovingAverage
(30); private readonly Clock _clock
= new Clock
(); public FpsText
(Font font,
uint characterSize
) : base("CURRENT FPS 60.00", font, characterSize
) => Style
= Styles
.Italic; public void Update
() { _movingAverage
.Update(_clock
.Restart().AsSeconds()); DisplayedString
= $
"CURRENT FPS {1/_movingAverage.Average:F2}"; } public new void Dispose
() { base.Dispose(); _clock
.Dispose(); }} Since SFML.Graphics.Text.Dispose() is not marked virtual, I have to apply the new keyword to ensure both the text itself
and the clock are disposed.
This works fine when it is known that the type is the subtype. However, this breaks when the runtime type is the subtype but the compile-time type is the supertype. For example, if you insert an FpsText into a List<Text> and then iteratively dispose each text, the clock is not disposed, causing a minor memory leak.
The fact that Dispose() is not marked virtual makes me think subclassing built-in types was not intended by the designers.
Is it bad practice to subclass primitive types, like Text? If so, what's the preferred approach? Should I favor composition over inheritance?