How to make C# Switch Statement use IgnoreCase

后端 未结 10 1018
孤独总比滥情好
孤独总比滥情好 2020-11-27 16:56

If I have a switch-case statement where the object in the switch is string, is it possible to do an ignoreCase compare?

I have for instance:

string s =         


        
相关标签:
10条回答
  • 2020-11-27 17:16

    An extension to the answer by @STLDeveloperA. A new way to do statement evaluation without multiple if statements as of c# 7 is using the pattern matching Switch statement, similar to the way @STLDeveloper though this way is switching on the variable being switched

    string houseName = "house";  // value to be tested
    string s;
    switch (houseName)
    {
        case var name when string.Equals(name, "Bungalow", StringComparison.InvariantCultureIgnoreCase): 
            s = "Single glazed";
        break;
    
        case var name when string.Equals(name, "Church", StringComparison.InvariantCultureIgnoreCase):
            s = "Stained glass";
            break;
            ...
        default:
            s = "No windows (cold or dark)";
            break;
    }
    

    The visual studio magazine has a nice article on pattern matching case blocks that might be worth a look.

    0 讨论(0)
  • 2020-11-27 17:23

    One possible way would be to use an ignore case dictionary with an action delegate.

    string s = null;
    var dic = new Dictionary<string, Action>(StringComparer.CurrentCultureIgnoreCase)
    {
        {"house",  () => s = "window"},
        {"house2", () => s = "window2"}
    };
    
    dic["HouSe"]();
    

    // Note that the call doesn't return text, but only populates local variable s.
    // If you want to return the actual text, replace Action to Func<string> and values in dictionary to something like () => "window2"

    0 讨论(0)
  • 2020-11-27 17:24

    In some cases it might be a good idea to use an enum. So first parse the enum (with ignoreCase flag true) and than have a switch on the enum.

    SampleEnum Result;
    bool Success = SampleEnum.TryParse(inputText, true, out Result);
    if(!Success){
         //value was not in the enum values
    }else{
       switch (Result) {
          case SampleEnum.Value1:
          break;
          case SampleEnum.Value2:
          break;
          default:
          //do default behaviour
          break;
       }
    }
    
    0 讨论(0)
  • 2020-11-27 17:25

    A simpler approach is just lowercasing your string before it goes into the switch statement, and have the cases lower.

    Actually, upper is a bit better from a pure extreme nanosecond performance standpoint, but less natural to look at.

    E.g.:

    string s = "house"; 
    switch (s.ToLower()) { 
      case "house": 
        s = "window"; 
        break;
    }
    
    0 讨论(0)
  • 2020-11-27 17:26

    Sorry for this new post to an old question, but there is a new option for solving this problem using C# 7 (VS 2017).

    C# 7 now offers "pattern matching", and it can be used to address this issue thusly:

    string houseName = "house";  // value to be tested, ignoring case
    string windowName;   // switch block will set value here
    
    switch (true)
    {
        case bool b when houseName.Equals("MyHouse", StringComparison.InvariantCultureIgnoreCase): 
            windowName = "MyWindow";
            break;
        case bool b when houseName.Equals("YourHouse", StringComparison.InvariantCultureIgnoreCase): 
            windowName = "YourWindow";
            break;
        case bool b when houseName.Equals("House", StringComparison.InvariantCultureIgnoreCase): 
            windowName = "Window";
            break;
        default:
            windowName = null;
            break;
    }
    

    This solution also deals with the issue mentioned in the answer by @Jeffrey L Whitledge that case-insensitive comparison of strings is not the same as comparing two lower-cased strings.

    By the way, there was an interesting article in February 2017 in Visual Studio Magazine describing pattern matching and how it can be used in case blocks. Please have a look: Pattern Matching in C# 7.0 Case Blocks

    EDIT

    In light of @LewisM's answer, it's important to point out that the switch statement has some new, interesting behavior. That is that if your case statement contains a variable declaration, then the value specified in the switch part is copied into the variable declared in the case. In the following example, the value true is copied into the local variable b. Further to that, the variable b is unused, and exists only so that the when clause to the case statement can exist:

    switch(true)
    {
        case bool b when houseName.Equals("X", StringComparison.InvariantCultureIgnoreCase):
            windowName = "X-Window";):
            break;
    }
    

    As @LewisM points out, this can be used to benefit - that benefit being that the thing being compared is actually in the switch statement, as it is with the classical use of the switch statement. Also, the temporary values declared in the case statement can prevent unwanted or inadvertent changes to the original value:

    switch(houseName)
    {
        case string hn when hn.Equals("X", StringComparison.InvariantCultureIgnoreCase):
            windowName = "X-Window";
            break;
    }
    
    0 讨论(0)
  • 2020-11-27 17:26

    It should be sufficient to do this:

    string s = "houSe";
    switch (s.ToLowerInvariant())
    {
      case "house": s = "window";
      break;
    }
    

    The switch comparison is thereby culture invariant. As far as I can see this should achieve the same result as the C#7 Pattern-Matching solutions, but more succinctly.

    0 讨论(0)
提交回复
热议问题