12

I want to ask someone who has stronger skills than me in C#.

Is it possible to reduce the following code

if(val > 20 && val < 40 )
...
else
if(val > 40 && val < 72 )
...
else
if(val > 72 && val < 88 )
...
else
...

Let's assume that I have over 10-11 if-else statements.

What's the best way to shorten the above code?

I thought at something like between in sql.

Orin MacGregor
  • 687
  • 1
  • 6
  • 12
Snake Eyes
  • 16,287
  • 34
  • 113
  • 221
  • Are you doing entirely different things in each block of code? You could have a list/array with 20,40,72, etc. as long as the block of code can be the same but with the index of which group it's in. – Servy Sep 05 '12 at 19:14
  • Its possible in VB but to my knowledge not in C#. – Magnus Sep 05 '12 at 19:15
  • @Magnus To be fair, you can trivially create library-based in syntax which matches the `Select Case` syntax in VB in conciseness (but yes, none exists in the framework). – Konrad Rudolph Sep 05 '12 at 19:15
  • try something in vb.net and i will try to convert to c# – Snake Eyes Sep 05 '12 at 19:16
  • You can build your own "between" function as shown here: http://stackoverflow.com/questions/5023213/is-there-a-between-function-in-c – Splendor Sep 05 '12 at 19:16
  • @KonradRudolph The C# equivalent would be alot of fall through cases. – Magnus Sep 05 '12 at 19:18
  • @Magnus No. I explicitly said “library-based syntax”. I didn’t mean `switch`. – Konrad Rudolph Sep 05 '12 at 19:19
  • It would be interesting to know what you are doing in each `if`. – Klaus Byskov Pedersen Sep 05 '12 at 19:20
  • @KonradRudolph well that is pretty much what he has right now. – Magnus Sep 05 '12 at 19:22
  • Maybe you could use an extension method that would return an enum, but I'm not sure about how much it would help. – Andre Calil Sep 05 '12 at 19:23
  • One of the things i'm missing in C# as opposed to VB.NET http://stackoverflow.com/a/68620/284240 – Tim Schmelter Sep 05 '12 at 19:23
  • @Magnus I meant [something like this](https://gist.github.com/3643325). There are libraries which provide such a syntax (and making this simple example compile is straightforward). (It could also use the syntax `With(13).To(42)` … I just chose the most straightforward interface). – Konrad Rudolph Sep 05 '12 at 19:43
  • I know you already picked an answer, but if you could clarify what you are doing when a val falls into one of the ranges, it might help future visitors to your question relate to your problem better. – Stuporman Sep 05 '12 at 20:49

6 Answers6

29

Define an extension method:

public static bool Between(this int source, int a, int b)
{
    return source > a && source < b;
}

Then, use it:

if (val.Between(20, 40))
//...

As oɔɯǝɹ correctly pointed out in his comment, you could go one step further and support all implementers of IComparable<T> with a generic extension method:

public static bool Between<T>(this T source, T a, T b) where T : IComparable<T>
{
    return source.CompareTo(a) > 0 && source.CompareTo(b) < 0;
}
Adam
  • 15,537
  • 2
  • 42
  • 63
  • 12
    you could make this a generic extension method as well: `public static bool Between(this T source, T a, T b) : where T: IComparable` – oɔɯǝɹ Sep 07 '12 at 19:26
4

An alternate way of doing that is to store your ranges in List and use the Contains function to find out if val is within the range, but without more information it looks like you have it as short as you can make it.

Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
Stuporman
  • 773
  • 6
  • 26
1

You can do a between, but it'll be as much, if not more typing to call it. In this case, if you really wanted what between does, then you'd be more concise with:

if(val >= 20 && val <= 88)
{
  if(val <= 40 )
  ...
  else if(val <= 72 )
  ...
}
else
 ...

Note that I'm using <= and >= to match the between behaviour. However, I'm assuming that you did want to neither have two things done for values exactly 40, exactly 72, nor nothing done (in your question, nothing would be done).

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
1

In my opinion it's good to have collection of ranges. And if logic inside blocks is pretty similar, you can store a delegate associated with this range.

RangeBase range = collection.FirstOrDefault(x => x.BelongsToRange(42));
if(range != null)
{
    dynamic result = range.SomeDelegate.DynamicInvoke();
}

Where RangeBase is a simple abstraction:

public abstract class RangeBase
{
    public int MinValue { get; private set; }
    public int MaxValue { get; private set; }

    public abstract Delegate SomeDelegate { get; }

    protected RangeBase(int minValue, int maxValue)
    {
        MinValue = minValue;
        MaxValue = maxValue;
    }

    public bool BelongsToRange(int number)
    {
        return number > MinValue && number < MaxValue;
    }
}
Ayaro
  • 144
  • 4
  • 1
    Like all programming, this is really a trade off between where you are placing your effort. I like the solution, but in the end it is enough work that you probably won't have saved any real-world time for this current project. However, his is a great solution if you find yourself requiring this kind of thing in many projects, in which case you would want to put the abstract bases into a library that you use with all future projects. – Stuporman Sep 05 '12 at 20:17
0
class Range{ public int first; public int second}

list<Range> rangeList= new list<Range>

write all combination in list with class

foreach( Range objRange in rangeList)
{
if( val>objRange.first && val<objRange.last)
{......
break;
}
}
-1
if(val > 72)
{

}
else 
{
   if(val > 40)
   {
     ...
   }
   else
   {
     ...   
   }
}
Aghilas Yakoub
  • 28,516
  • 5
  • 46
  • 51