简体   繁体   中英

I need to replace a C# switch with something more compact

I have the following code:

switch (pk.Substring(2, 2))
{
    case "00":
        ViewBag.Type = _reference.Get("14", model.Type).Value;
        break;
    case "01":
        ViewBag.Type = _reference.Get("18", model.Type).Value;
        break;
}

It does the job but does not look very clean to me. Is there some way I could make this code a bit smaller. I was thinking to just have the number 14 or 18 as a variable but I am not sure the best way to code if I should use if-else or some other way.

You could use a static dictionary as a map instead of a switch-statement.

 static readonly Dictionary<string, string> map = new Dictionary<string, string> {
     { "00", "14" },
     { "01", "18" },
     // ... more ...
 };

 // ... in your method ...

 string str = pk.Substring(2, 2);
 string val;

 if (!map.TryGetValue(str, out val))
 {
     // Handle error, like in the "default:" case of the switch statement
 }
 else
 {
     ViewBag.Type = _reference.Get(val, model.Type).Value;
 }

However, I would only do this, if there are really a lot of mappings that maybe can even be "read" from an external source like a configuration file.

Also note, that if the "key" is really a consecutive sequence of integers starting at 0, you might be able to use an array, where the "key" is simply the index into it.

 static readonly string[] map = new string[] {
    "14", "18", ...
 };

 int index = Int32.Parse(pk.Substring(2, 2)); // Error handling elided.

 if (index < 0 || index > map.Length)
 {
     // Handle error, like in the "default:" case of the switch statement
 }
 else
 {
     ViewBag.Type = _reference.Get(map[index], model.Type).Value;
 }

Otherwise rather stay with an explicit switch statement (possibly factoring out the assignment for more terse code):

 string val;

 switch (pk.Substring(2, 2))
 {
    case "00":
      val = "14";
      break;
    case "01":
      val = "18";
      break;

    // ... more ...

    default:
      // Error handling for unknown switch-value.
      break;
 }

 ViewBag.Type = _reference.Get(val, model.Type).Value;

It seems that there is some relationship between "00"->"14" and "01"->"18". I believe this relationship results from the business logic. You should wrap the logic and make the code in your controller clear. Finally the code in the controller should look like:

public ActionResult MyAction()
{
    //some code

    ViewBag.Type = TypeProvider.GetType(pk, model.Type);

    //return something
}

class TypeProvider
{
    Dictionary<string, string> relations = ...
         //a dictionary stores "00"->"14" logics

    public static SomeType GetType(string pk, Type modelType)
    {
        return _reference.Get(relations[pk.SubString(2,2)], modelType).Value;
    }
}
var data = pk.Substring(2, 2);
var choice = data == "00" ? "14" : (data=="01"?"18":"");
if (choice != string.Empty) ViewBag.Type = _reference.Get(choice, model.Type).Value;

I use mapping extensions fot that kind of code:

ViewBag.Type = pk.Substring(2, 2)
.Map("00", x => GetViewBagValue("14"))
.Map("01", x => GetViewBagValue("18"))

and in your case this method:

private ViewBagValue GetViewBagValue(string value)
{
    return _reference.Get(value, model.Type).Value; 
}

I use this. You could easily change it to generic or use eg object[] instead. Not super efficient, but very compact:

public static class Util {
    public static string Switch(string value, params string[] nameValues) {
        for (int x = 0; x < nameValues.Length; x += 2) {
            if (nameValues[x] == value) {
                return nameValues[x + 1];
            }
        }
        return string.Empty;
    }
}

Then just call that like this:

var res = Util.Switch("test2", "test1", "res1", "test2", "res2");

Best of luck!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM