62

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
  • 346
  • 1
  • 3
  • 10
pmerino
  • 5,560
  • 10
  • 54
  • 75

12 Answers12

127

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,534
  • 2
  • 10
  • 9
  • 1
    +1 This works perfectly now. And to anyone wondering you can access the value of the case via the "x" variable in this scenario. – Patrick Feb 05 '20 at 04:38
  • Also, you can use any var name-except-the one in the switch statement to evaluate. Then, you can refer to the original variable/expression in the code that follows. – Yumi Koizumi Jul 27 '21 at 01:07
  • @Patrick, can you clarify what you mean by the "x" variable? Sorry I'm sure it's obvious. – David Mays Aug 18 '21 at 17:08
  • I feel so dumb asking about this simple answer, but isn't "break" also mandatory in C# case statements? – David Mays Aug 19 '21 at 16:54
  • In case statements you can leave the break if you use return. – Lakedaimon Aug 19 '21 at 21:34
35

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,324
  • 6
  • 68
  • 79
  • 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
  • 9
    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
30

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
  • 16,745
  • 16
  • 96
  • 110
Tigran
  • 60,656
  • 8
  • 83
  • 120
21

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://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/switch-expression

Jesús Jiménez
  • 221
  • 2
  • 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
16

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
  • 347
  • 4
  • 13
  • 1
    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
4
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
  • 41
  • 1
  • Thanks this worked perfectly for me, I had one small change that might help others that don't just have string message private static string GetRoles(IEnumerable roles) Here was my switch statement. switch (switchStrings.FirstOrDefault(s => roles.Select(t => t.RoleName).Contains(s))) – Mark Monforti Apr 28 '20 at 13:57
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,348
  • 3
  • 38
  • 53
shenhengbin
  • 4,174
  • 1
  • 22
  • 33
2

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
  • 76
  • 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,827
  • 4
  • 28
  • 43
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,606
  • 2
  • 38
  • 59
Mark Monforti
  • 445
  • 4
  • 7
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,602
  • 2
  • 16
  • 20
  • 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
-5
switch(message)
{
  case "test":
    Console.WriteLine("yes");
    break;                
  default:
    if (Contains("test2")) {
      Console.WriteLine("yes for test2");
    }
    break;
}
Jeroen Heier
  • 3,196
  • 15
  • 30
  • 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