81

I'm doing an C# app where I use

if ((message.Contains("test")))
{
   Console.WriteLine("yes");
} else if ((message.Contains("test2"))) {
   Console.WriteLine("yes for test2");
}

There would be any way to change to switch() the if() statements?

one noa
  • 345
  • 1
  • 3
  • 10
pmerino
  • 5,900
  • 11
  • 57
  • 76

12 Answers12

152

Correct final syntax for [Mr. C]s answer.

With the release of VS2017RC and its C#7 support it works this way:

switch(message)
{
    case string a when a.Contains("test2"): return "no";
    case string b when b.Contains("test"): return "yes";
}

You should take care of the case ordering as the first match will be picked. That's why "test2" is placed prior to test.

Lakedaimon
  • 1,784
  • 2
  • 11
  • 10
36

Nope, switch statement requires compile time constants. The statement message.Contains("test") can evaluate true or false depending on the message so it is not a constant thus cannot be used as a 'case' for switch statement.

Teoman Soygul
  • 25,584
  • 6
  • 69
  • 80
  • 2
    So I only can use `if()`? That's pretty messy :( – pmerino Aug 24 '11 at 12:45
  • @zad0xsis: Do you have a lot of these? If so, you could potentially abstract the idea somewhat... – Jon Skeet Aug 24 '11 at 12:51
  • yeah I've got a lot of `if()` :( – pmerino Aug 24 '11 at 13:03
  • 10
    It's worth noting - this will change with C# 7. Patterns can be used in case clauses. As of this writing, this feature is available in Visual Studio 15 Preview 4. https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/ – Mr. C Dec 15 '16 at 18:36
34

This will work in C# 8 using a switch expresion

var message = "Some test message";

message = message switch
{
    string a when a.Contains("test") => "yes",
    string b when b.Contains("test2") => "yes for test2",
    _ => "nothing to say"
};

For further references https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/switch-expression

Jesús Jiménez
  • 366
  • 3
  • 5
  • 5
    I find switch expressions a very strange syntax that is hard to remember. Always find myself looking it up if I haven't used it in a few months... – GameSalutes Dec 07 '21 at 21:08
34

If you just want to use switch/case, you can do something like this, pseudo-code:

    string message = "test of mine";
    string[] keys = new string[] {"test2",  "test"  };

    string sKeyResult = keys.FirstOrDefault<string>(s=>message.Contains(s));

    switch (sKeyResult)
    {
        case "test":
            Console.WriteLine("yes for test");
            break;
        case "test2":
            Console.WriteLine("yes for test2");
            break;
    }

But if the quantity of keys is a big, you can just replace it with dictionary, like this:

static Dictionary<string, string> dict = new Dictionary<string, string>();
static void Main(string[] args)
{
    string message = "test of mine";      

    // this happens only once, during initialization, this is just sample code
    dict.Add("test", "yes");
    dict.Add("test2", "yes2"); 


    string sKeyResult = dict.Keys.FirstOrDefault<string>(s=>message.Contains(s));

    Console.WriteLine(dict[sKeyResult]); //or `TryGetValue`... 
 }
JohnB
  • 18,046
  • 16
  • 98
  • 110
Tigran
  • 61,654
  • 8
  • 86
  • 123
21

Simple yet efficient with c#

 string sri = "Naveen";
    switch (sri)
    {
        case var s when sri.Contains("ee"):
           Console.WriteLine("oops! worked...");
        break;
        case var s when sri.Contains("same"):
           Console.WriteLine("oops! Not found...");
        break;
    }
Nawin
  • 485
  • 8
  • 14
  • 5
    If you don't need the value of `var s` (as you don't in your example) you can use `var _` to discard it. – k3davis Jan 31 '22 at 16:07
  • Similarly to the answer above when you don't need the value of `var s`, you can use `not null` to discard it. – Tomy Apr 14 '23 at 07:20
7
string message = "This is test1";
string[] switchStrings = { "TEST1", "TEST2" };
switch (switchStrings.FirstOrDefault<string>(s => message.ToUpper().Contains(s)))
{
    case "TEST1":
        //Do work
        break;
    case "TEST2":
        //Do work
        break;
    default:
        //Do work
        break; 
}
Stegmann
  • 71
  • 1
  • 1
4

You can do the check at first and then use the switch as you like.

For example:

string str = "parameter"; // test1..test2..test3....

if (!message.Contains(str)) return ;

Then

switch(str)
{
  case "test1" : {} break;
  case "test2" : {} break;
  default : {} break;
}
Druid
  • 6,423
  • 4
  • 41
  • 56
shenhengbin
  • 4,236
  • 1
  • 24
  • 33
3

Faced with this issue when determining an environment, I came up with the following one-liner:

string ActiveEnvironment = localEnv.Contains("LIVE") ? "LIVE" : (localEnv.Contains("TEST") ? "TEST" : (localEnv.Contains("LOCAL") ? "LOCAL" : null));

That way, if it can't find anything in the provided string that matches the "switch" conditions, it gives up and returns null. This could easily be amended to return a different value.

It's not strictly a switch, more a cascading if statement but it's neat and it worked.

0xFF
  • 86
  • 5
2

Some custom swtich can be created like this. Allows multiple case execution as well

public class ContainsSwitch
{

    List<ContainsSwitch> actionList = new List<ContainsSwitch>();
    public string Value { get; set; }
    public Action Action { get; set; }
    public bool SingleCaseExecution { get; set; }
    public void Perform( string target)
    {
        foreach (ContainsSwitch act in actionList)
        {
            if (target.Contains(act.Value))
            {
                act.Action();
                if(SingleCaseExecution)
                    break;
            }
        }
    }
    public void AddCase(string value, Action act)
    {
        actionList.Add(new ContainsSwitch() { Action = act, Value = value });
    }
}

Call like this

string m = "abc";
ContainsSwitch switchAction = new ContainsSwitch();
switchAction.SingleCaseExecution = true;
switchAction.AddCase("a", delegate() { Console.WriteLine("matched a"); });
switchAction.AddCase("d", delegate() { Console.WriteLine("matched d"); });
switchAction.AddCase("a", delegate() { Console.WriteLine("matched a"); });

switchAction.Perform(m);
hungryMind
  • 6,931
  • 4
  • 29
  • 45
1

Stegmenn nalied it for me, but I had one change for when you have an IEnumerable instead of a string = message like in his example.

private static string GetRoles(IEnumerable<External.Role> roles)
{
    string[] switchStrings = { "Staff", "Board Member" };
    switch (switchStrings.FirstOrDefault<string>(s => roles.Select(t => t.RoleName).Contains(s)))
    {
        case "Staff":
            roleNameValues += "Staff,";
            break;
        case "Board Member":
            roleNameValues += "Director,";
            break;
        default:
            break;
    }
}
brichins
  • 3,825
  • 2
  • 39
  • 60
Mark Monforti
  • 463
  • 4
  • 8
0

This will work in C# 7. As of this writing, it has yet to be released. But if I understand this correctly, this code will work.

switch(message)
{
    case Contains("test"):
        Console.WriteLine("yes");
        break;
    case Contains("test2"):
        Console.WriteLine("yes for test2");
        break;
    default:
        Console.WriteLine("No matches found!");
}

Source: https://blogs.msdn.microsoft.com/dotnet/2016/08/24/whats-new-in-csharp-7-0/

Mr. C
  • 1,652
  • 2
  • 16
  • 22
  • 4
    No, this does not work. `Contains does not exist in the current context.` – user9993 Apr 06 '17 at 08:28
  • I cannot see your example on the link provided. – Willy David Jr Oct 23 '18 at 18:36
  • Does not work, you should test it first before sharing your answer. See [Lakedaimon's solution](https://stackoverflow.com/a/41428406/3009574) for the correct syntax. – pogosama Jun 19 '19 at 06:39
  • 1
    This is pretty close. Mr. C is correct in his answer. "This will work in C# 7" The syntax for this to work is slightly off though... Review Lakedaimon's answer for correct syntax. – Patrick Feb 05 '20 at 04:09
-6
switch(message)
{
  case "test":
    Console.WriteLine("yes");
    break;                
  default:
    if (Contains("test2")) {
      Console.WriteLine("yes for test2");
    }
    break;
}
Jeroen Heier
  • 3,520
  • 15
  • 31
  • 32
  • 4
    Hi, welcome to stack overflow. For a useful answer explain why this is an answer to the question. – Jeroen Heier Dec 28 '19 at 07:41
  • 1
    in C# switch condition is not powerful as KOTLIN so if you want to implement String.contains() in condition state of switch I think we have to separate our condition in default part – mehdi navab Jan 04 '20 at 10:59