I have an occasion of code in which I will draw a different set of buttons in a screen (depending on the number of the buttons).
One thought (and my current implementation) is to use an action array and call a different action
Action[] array = new Action[9];
array[0] = one;
array[1] = two;
array[2] = three;
array[3] = four;
array[4] = five;
array[5] = six;
array[6] = seven;
array[7] = eight;
array[8] = nine;
array[buttons.Count - 1]();
So depending on the number of buttons I call the specific drawing method. Another implementation might be using switch case and would look like something this
switch(buttons.count){
case 1: one(); break;
case 2: two(); break;
.
.
.
.
case 9: nine();break;
}
Are there any pros and cons of using versus the other?
Are there any efficiency differences?
2
IMHO the first one is in most cases preferable. First, in C# you can rewrite the initialization much shorter as
Action[] array = new[]{one, two, three, four, five, six, seven,eight,nine};
But the real advantage comes when you have to change your actions later, for example, by introducing an additional argument. You then have to change only this line
array[buttons.Count - 1](myArgument);
The switch
variant instead needs changes in 9 places instead:
switch(buttons.count){
case 1: one(myArgument); break;
case 2: two(myArgument); break;
...
That is because the switch
variant does not follow the “Don’t Repeat Yourself” (DRY) principle. Imagine what happens when you have not just 9 actions, but 50, or you have to introduce more arguments, or to process a return code from the action / function.
And don’t worry too much about performance – in most real-world cases the performance difference is negligible. When you suspect it is not, you will have to try and measure if a replacement by a switch statement does really bring the necessary performance gain.
3
Well, there are many arguments one way or the other.
But the most important thing to realize: it doesn’t matter (in this case).
- Performance wise, the drawing (and subsequent rendering of it) will take order of magnitudes longer than the invocation of the right drawing functions.
- Complexity wise, the drawing code will most likely also crushingly outweigh the invocation issue. The fact that you need nine different drawing functions makes this pretty clear.
If you are actually concerned with this, the right thing to do is to blackbox the decision in a separate class, where a button count goes in and a drawing function comes out. Thus no other code depends on how this is accomplished and you can change that any time you have a reason to.
2
Of course there are pro and con effects; if there weren’t, the community would long ago have figured them out, and everybody would agree to do always the one and never the other.
A switch
statement is fine if the things you switch over have only one behaviour. A button does something when clicked, so that seems appropriate. But as soon as the variable you’re switching over has more than one behaviour, you would need a second switch statement listing exactly the same cases. That’s a violation of DRY, and it will get worse with every additional thing that’s added to the class. And let’s be honest: when was the last time you saw an established class get less complex?
An array of objects that all dispatch the same messages avoids this problem. It may or may not be less efficient than a switch
compiled into a jump table. If it is, the difference may or may not be worth compromising other principles. If it is, it may or may not be a good idea if you do compromise them now, considering that the system will evolve further and today’s small compromise might become a huge maintenance headache for years to come.
This is why only you know whether to choose one option over the other: because the particulars of your application probably outweigh the general pressures that we can enumerate for you.
(It’s a bit like prejudice: when all you know about a web application is that it was written by volunteers in PHP, it’s fine to assume that it’s probably on the less secure side vs. one that is used by a major bank. After all, many such apps are in fact insecure. But if you have concrete examples of either web app, looking at the particulars of both instances is virtually always smarter than relying on general maxims, i.e. prejudice.)