In C#, the switch statement doesn't allow cases to span ranges of values. I don't like the idea of using if-else loops for this purpose, so are there any other ways to check numeric ranges in C#?
            Asked
            
        
        
            Active
            
        
            Viewed 2.0k times
        
    12
            
            
         
    
    
        TheLethalCoder
        
- 6,668
- 6
- 34
- 69
 
    
    
        Kenny
        
- 819
- 1
- 9
- 24
- 
                    You can't really do it in C# (unless it's a small range of numbers you can list in blocks), but, for once, you **can** in VB.Net - http://stackoverflow.com/questions/1009902/select-case-to-check-range-of-a-decimal-number funnily enough – dash Jul 05 '12 at 06:58
- 
                    Well you can have a method returning bool which takes in the range and then if loops, its simple, readable and does the work well – V4Vendetta Jul 05 '12 at 06:58
- 
                    http://stackoverflow.com/questions/68578/multiple-cases-in-switch You cannot do this in C#. Check the answer above. – Dzung Nguyen Jul 05 '12 at 07:22
- 
                    **Important note** : Ranges are supported in switch case starting C# v7 - [Switch case: can I use a range instead of a one number](https://stackoverflow.com/q/20147879/465053). So, if you feel like better upgrade from C# v3.5 to v7 instead. – RBT May 18 '18 at 11:45
7 Answers
16
            You can use a HashTable respectively Dictionary to create a mapping of Condition => Action.
Example:
class Programm
{
    static void Main()
    {
        var myNum = 12;
        var cases = new Dictionary<Func<int, bool>, Action>
        { 
            { x => x < 3 ,    () => Console.WriteLine("Smaller than 3")   } ,
            { x => x < 30 ,   () => Console.WriteLine("Smaller than 30")  } ,
            { x => x < 300 ,  () => Console.WriteLine("Smaller than 300") } 
        };
        cases.First(kvp => kvp.Key(myNum)).Value();
    }
}
This technique is a general alternative to switch, especially if the actions consists only of one line (like a method call).
And if you're a fan of type aliases:
using Int32Condition = System.Collections.Generic.Dictionary<System.Func<System.Int32, System.Boolean>, System.Action>;
...
    var cases = new Int32Condition()
    { 
        { x => x < 3 ,    () => Console.WriteLine("Smaller than 3")   } ,
        { x => x < 30 ,   () => Console.WriteLine("Smaller than 30")  } ,
        { x => x < 300 ,  () => Console.WriteLine("Smaller than 300") } 
    };
 
    
    
        Saverio Terracciano
        
- 3,885
- 1
- 30
- 42
 
    
    
        sloth
        
- 99,095
- 21
- 171
- 219
- 
                    2But you should not take a dictionary (take a list of KeyValuePair, Tuple or sth self defined) otherwise you can't predict in which order the Funcs are called for testing. – Oliver Jul 05 '12 at 08:19
- 
                    1Interesting but if I saw this pattern as a replacement of if/else in real project I'm submitting it to http://thedailywtf.com :) – Stilgar Jul 05 '12 at 08:23
- 
                    This solution is outright ridiculous. Good for a quiz, but very bad for production code. It is slow, as it wastes memory, and causes too much calls which cannot be inlined. – Nick Jul 05 '12 at 08:28
- 
                    This code doesn't even *work*. Since a dictionary is inierently unordered you can't be sure that `x < 3` will be checked before `x < 30`. That it does in one or two tests cases doesn't mean it will hold true. A `Dictionary` is simply the wrong data structure here, unless you ensure that the methods can be called in any order (which you haven't done). As mentinoed by Oliver, a list of tuples would be one way to ensure ordering, and is semantically correct. Note that this isn't really any different than a series of `if/else if` statements either. – Servy Jun 21 '13 at 14:50
5
            
            
        Nope. Of course, if the ranges are small you could use the
case 4:
case 5:
case 6:
   // blah
   break;
approach, but other than that: no. Use if/else.
 
    
    
        Marc Gravell
        
- 1,026,079
- 266
- 2,566
- 2,900
4
            
            
        if the interval of the ranges is constant, you can try
        int num = 11;
        int range = (num - 1) / 10; //here interval is 10
        switch (range)
        {
            case 0:
                Console.Write("1-10");
                break; // 1-10
            case 1:
                Console.Write("11-20");
                break; // 11-20
            // etc...
        }
Output would be: "11-20"
if interval is variable then use if/else
 
    
    
        Habib
        
- 219,104
- 29
- 407
- 436
1
            
            
        No. At least nothing which is more beautiful.
Also there is no C# 3.5 only .NET 3.5 and C# 3.0
 
    
    
        Stilgar
        
- 22,354
- 14
- 64
- 101
1
            
            
        Try something like this
 private void ExecuteInRange(Dictionary<Range,Action<int>> ranges)
    {
        foreach (var range in ranges)
        {
            if (range.Key.Value < range.Key.Max && range.Key.Value > range.Key.Max)
                range.Value(range.Key.Value);
        }
    }
public class Range
{
    public int Min { get; set; }
    public int Max { get; set; }
    public int Value { get; set; }
}
 
    
    
        Preben Huybrechts
        
- 5,853
- 2
- 27
- 63
1
            
            
                int b;
        b = Int32.Parse(textBox1.Text);
        int ans = (100-b)/3; //the 3 represents the interval
        //100 represents the last number
        switch(ans)
        {
           case 0:
                MessageBox.Show("98 to 100");
           break;
           case 1:
                MessageBox.Show("95 to 97");
           break;
           case 2:
                MessageBox.Show("92 to 94");
           break;
           case 3:
                MessageBox.Show("89 to 91");
           break;
           case 4:
                MessageBox.Show("86 to 88");
           break;
           default:
                MessageBox.Show("out of range");
           break;
-1
            
            
        A sort of nested-shorthand if-else thing works, and is clean.
myModel.Value = modelResult >= 20 ? 5 : modelResult >= 14 ? 4 : modelResult >= 5 ? 3 : modelResult >= 2 ? 2 : modelResult == 1 ? 1 : 0;
 
    
    
        blomster
        
- 768
- 2
- 10
- 27
