5

Consider this code:

if (results.Contains(14))
{
    //anything
}
else if (results.Contains(15))
{
    //anything
}
else if (results.Contains(16))
{
    //anything
}

I want write this code with switch case :

switch (results)
{
    case results.Contains(14):
}

But we can't write this in C#.

What is the clear way for write the above code, knowing that results is a long[]?

huysentruitw
  • 27,376
  • 9
  • 90
  • 133

9 Answers9

8

What's wrong with this:

if (results.Contains(14) || results.Contains(15) || results.Contains(16))
{
  new Exception("anything");
}
ganders
  • 7,285
  • 17
  • 66
  • 114
  • Ah, I see the question was updated to throw an exception with the value that you're checking in the contains, which makes this answer not relevant anymore... – ganders Aug 13 '13 at 13:06
  • Please update your answer –  Aug 13 '13 at 13:11
4

since it is probably in a string that has that number one solution would be to use a regular expression.

var m = System.Text.RegularExpressions.Regex.Matches(results, @"\d{1,2}")[0];
throw new Exception(m);

(NOTE: I did this in notepad so it might require a small tweak)

You will have to probably play with the match syntax as this is only good for 1-2 numbers. in a string.

Robert Snyder
  • 2,399
  • 4
  • 33
  • 65
4

What are you really trying to do?

The following should work, but I am not sure if that's what you had in mind:

int[] values = {14, 15, 16};
foreach (var n in values) {
  if(result.Contains(n)) 
     throw new Exception(n.ToString()) 
}

-- EDIT: the question has changed considerably so here's an update --

I would probably use plain if-else but if you have many options or complex logic (e.g. not just results.Contains()), sometimes it is better to choose tables:

int[] results = {13, 14, 15};
action_map = new Dictionary<int, Action>();
action_map[14] = () => Console.Out.WriteLine("14");
action_map[15] = () => Console.Out.WriteLine("15");
action_map[16] = () => { throw new InvalidOperationException(); };
action_map[0] = () => {}; // NOP, default case - executed if no match found

var action_key = dict.Keys.FirstOrDefault(k => results.Contains(k));
action_map[action_key]();

In real code, I would probably wrap it into a class:

var table = new FnTable();
table.Add(14, () => Console.Out.WriteLine("14"));
table.Add(15, () => Console.Out.WriteLine("15"));
table.Add(16, () => { throw new InvalidOperationException(); });

int[] results = {13, 14, 15};
table.ExecuteFirstFrom(results);
Zdeslav Vojkovic
  • 14,391
  • 32
  • 45
3

I like approach with action dictionaries

        var swticher = new Dictionary<long, Func<Exception>>()
        {
            {15,()=>new Exception("15")},
            {14,()=>new Exception("14")}
        };

        throw swticher[14].Invoke();

Of course more complex examples will show power of this approach :)

Why to use dictionaries instead of switches: https://stackoverflow.com/a/11617459/1714342

Abstract:

The short answer is that the switch statement executes linearly, while the dictionary executes logarithmically.

Community
  • 1
  • 1
Kamil Budziewski
  • 22,699
  • 14
  • 85
  • 105
  • Your quote is incorrect. `switch`, in C#, can actually be implemented as a dictionary. That's why all case statements must be compile time constants, rather than any executable expression. Read the complete analysis of your own link for the details. – Servy Aug 13 '13 at 14:16
3

Usually a clear way to replace if/switch statements is to use polymorphism. However, in the example you've provided the if statements are so trivial, that they can be replaced by a simple algorithm which calculates the contents of the exception, as stated in Robert Snyder's answer.

BartoszKP
  • 34,786
  • 15
  • 102
  • 130
2

switch (C# Reference):

Each case label specifies a constant value.

In your expected sample code, results.Contains(14) is not a constant value, so the syntax will not be valid.

Alex Filipovici
  • 31,789
  • 6
  • 54
  • 78
2

You can use a switch statement inside a foreach:

long[] results = new long[] { 15, 14, 16 };
foreach (long v in results)
{
    switch (v)
    {
        case 14:
            // anything
            break;
        case 15:
            // anything
            break;
        case 16:
            // anything
            break;
    }
}

And to better match with your question, you should order the array first and get out the foreach after a match:

long[] results = new long[] { 15, 14, 16 };
Array.Sort(results);
foreach (long v in results)
{
    switch (v)
    {
        case 14:
            // anything
            break;
        case 15:
            // anything
            break;
        case 16:
            // anything
            break;
        default:
            continue; // continue the foreach loop
    }
    break; // break the foreach loop because we had a valid match
}
huysentruitw
  • 27,376
  • 9
  • 90
  • 133
2

I would not actually recommend to do it this way, but if you're really into switch statements...

long? CheckSpecialNumbers(long[] res)
{
    var specialNumbers = new List<long>() {14, 15, 16};
    var inters= specialNumbers.Intersect(res);
    return inters.Count() > 0 ? (long?)inters.First() : null;
}

then you could do:

long? res = CheckSpecialNumbers(results);

switch (res)
{
    case 14:
        Console.WriteLine(14);
        break;
    case 15:
        Console.WriteLine(15);
        break;
    case 16:
        Console.WriteLine(16);
        break;
}
Paolo Falabella
  • 24,914
  • 3
  • 72
  • 86
1

I want write this code with switch case

A switch-case statement is used to branch the execution path according to the value of a given variable. The OP wants to branch according to the value of a Boolean expression, specifically, the return value of Contains. This can only be done using an if-else statement. Writing switch (results) doesn't make sense, since results is an array of integers.

kol
  • 27,881
  • 12
  • 83
  • 120