I'm writing a simple game in Unity, and learning C# on my own. Currently I'm doing first pass on the scoring system. I decided to do this with native c# events. So my first idea was to have the Score class responsible for counting/keeping player score. This class would receive events from objects implementing the IScoreable
interface.
It would look something like this (example code):
public interface IScoreable {
event Action<IScoreable> Scored;
int Value { get; set; }
}
public class Score {
public void addScore(IScoreable scoreable) {
//do something with scoreable.Value
}
}
In theory, it's decent enough, but I had a problem with coupling:
With just the above code, Score needs to know about all possible objects that implement IScoreable
, so it can subscribe to the Scored event. Considering there will be a lot of various objects implementing this interface - it may get instantiated from different parts of code, I don't see any "clean" way of doing this.
Another option would be, to have every IScoreable
object register itself with Score object, but this again would create strong coupling. For example adding another player, and subsequently another Score instance, would require rewriting all classes implementing IScoreable
)
Which leaves me with two alternatives (that I see). Create some kind of event manager/ aggregator. This option is now for me (subjectively speaking, I like how in c# events are strongly connected to class that defines them).
Another option, the one I'm leaning towards, is to use a static event for this. This would require a switch from interface to abstract class for IScoreable
. Which could be a big deal with c# single inheritance, but in this case it isn't (Unity component based approach, discourages deep inheritance trees) I think it would fit this use case quite well.
public abstract class Scorable {
public static event Action<Scorable> Scored;
protected virtual void onScored() { if (Scored != null) Scored(this); }
public int Value { get; set; }
}
Score object would simply subscribe to Scored, and be done. Every class inheriting from Scoreable would call base.onScore
when needed, and be done. No additional classes would be needed. Other than possibility of memory leak - if not careful I don't see downsides to this.
But since the use of static events seems to be discouraged, I have my doubts, maybe because of my inexperience I don't see a simple solution.
So the question... Is there a better (cleaner, simpler) solution to my problem? Would you advise against the use of static event in this case?