1

I have this code where each part of the switch returns a value to ModeMessage2. Is it possible using the new C# switch expressions (or any other code optimization) to optimize the way this switch works?

switch (Settings.Mode)
{
    case MO.Learn:
        ModeMessage2 =
            "Use this mode when you are first learning the phrases and their meanings.";
        if (Settings.Cc == CC.H)
        {
            Settings.Cc = CC.JLPT5;
            App.cardSetWithWordCount = null;
            App.DB.RemoveSelected();
        }
        break;
    case MO.Practice:
        ModeMessage2 =
             "Use this mode to help you memorize the phrases and their meanings.";
        if (Settings.Cc == CC.H)
        {
            Settings.Cc = CC.JLPT5;
            App.cardSetWithWordCount = null;
            App.DB.RemoveSelected();
        }
        break;
    case MO.Quiz:
        if (Settings.Cc == CC.H)
        {
            Settings.Cc = CC.JLPT5;
            App.cardSetWithWordCount = null;
            App.DB.RemoveSelected();
        }
        App.DB.UpdSet(SET.Adp, false);
        ModeMessage2 =
            "Use this mode to run a self marked test.";
        break;
}
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
Alan2
  • 23,493
  • 79
  • 256
  • 450
  • 1
    A switch has no return value. You return a string you need a string variable that is set in each case statement. The string variable will be defined before the "switch" statement. – jdweng Nov 22 '19 at 16:53

3 Answers3

2

Your code is similar to the following, though if there are side effects of setting ModeMessage2 or the other properties then the order that things happen might matter in which case this is not technically 100% equivalent.

IList<MO> specialModes = new[] { MO.Learn, MO.Practice, MO.Quiz };

if (specialModes.Contains(Settings.Mode) && Settings.Cc == CC.H) {
   Settings.Cc = CC.JLPT5;
   App.cardSetWithWordCount = null;
   App.DB.RemoveSelected();
}

ModeMessage2 = Settings.Mode switch {
   MO.Learn => "Use this mode when you are first learning the phrases and their meanings.",
   MO.Practice => "Use this mode to help you memorize the phrases and their meanings.",
   MO.Quiz => "Use this mode to run a self marked test.",
   _ => "Unknown mode value" // or throw
};

if (Settings.Mode == MO.Quiz)
   App.DB.UpdSet(SET.Adp, false);
Dave Cousineau
  • 12,154
  • 8
  • 64
  • 80
1
var modeMessage2 = Settings.Mode switch
{
    MO.Learn => "Use this mode when you are first learning the phrases and their meanings.",
    MO.Practice => "Use this mode to help you memorize the phrases and their meanings.",
    MO.Quiz => "Use this mode to run a self marked test."
}

if (Settings.Cc == CC.H)
{
    Settings.Cc = CC.JLPT5;
    App.cardSetWithWordCount = null;
    App.DB.RemoveSelected();
}

if (Settings.Mode == MO.Quiz) {
    App.DB.UpdSet(SET.Adp, false);
}

paul
  • 21,653
  • 1
  • 53
  • 54
1

You should use a dictionary to do this --

 Dictionary<TypeOf(Settings.Mode), string> map = new Dictionary<TypeOf(Settings.Mode), string>();

 map.Add(MO.Learn,"Use this mode when you are first learning the phrases and their meanings.");
 map.Add(MO.Practice,"Use this mode to help you memorize the phrases and their meanings.");
 map.Add(MO.Quiz,"Use this mode to run a self marked test.");


 ModeMessage2 = map[Settings.mode]);

This will be much faster than any switch statement and easier to maintain.

You could also use an array if that makes sense.


Note to commenters below: I'm making the following assumptions, which could be false in some cases but not in the general case. 1) the code is written in a way that the "allocation" only happens once for the lifetime of the code -- in this case if the map is used more than once, you get savings so that after N time the cost of allocation goes to 0. 2) We don't know the type of the key, comments that assume it is a string are making an assumption that might not be true. EVEN SO, any "fast" comparisons of strings is using a hash which is the same thing a dictionary uses to get it speed. 3) It is well known that the slowest thing you can do in programming is a branch. A dictionary (or array map) allow you to not have any branches, just a calculation to a memory location.

Hogan
  • 69,564
  • 10
  • 76
  • 117
  • Faster than direct comparisons? – Panagiotis Kanavos Nov 22 '19 at 17:17
  • 1
    "much faster than any switch statement"? I would think for three values that a dictionary would be a lot slower than a switch. – Dave Cousineau Nov 22 '19 at 17:17
  • `This will be much faster than any switch statement`. It won't. For larger collection, sure the dictionary will be faster (Log(N) vs N). For `N = 3` there will be no noticeable difference – HappyPengins Nov 22 '19 at 17:17
  • Allocating the dictionary and populating it will actually make it slower – HappyPengins Nov 22 '19 at 17:18
  • Note that a switch statement is *incredibly* well optimized for strings. It starts off with a linear search for a small number of strings, then it moves onto embedding a hash function in your assembly and doing a tree search using the hash code, then finally it moves onto using a dictionary. – canton7 Nov 22 '19 at 17:33