257

How can I do this elegantly with C#?

For example, a number can be between 1 and 100.

I know a simple if (x >= 1 && x <= 100) would suffice; but with a lot of syntax sugar and new features constantly added to C#/.Net this question is about more idiomatic (one can all it elegance) ways to write that.

Performance is not a concern, but please add performance note to solutions that are not O(1) as people may copy-paste the suggestions.

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
Sergio Tapia
  • 40,006
  • 76
  • 183
  • 254
  • 28
    Re: Your "edit" - **simple is elegant**. I personally find the if statement more elegant than any non-standard means of doing this check... – Reed Copsey Jul 06 '10 at 17:37
  • 5
    "Everything should be made as simple as possible, but not simpler." - Albert Einstein – corsiKa Jul 06 '10 at 17:40
  • @Reed: Please don't be so pedantic. Of course using something more than an if is overkill, but I want to see if there is something more baroque in nature. – Sergio Tapia Jul 06 '10 at 17:41
  • 3
    @Sergio: I don't feel I am being pedantic. I feel that people often abuse extension methods and other tools in the language in order to replace things that are already simple. There are hundreds of ways to compare two int values, but using anything but the more obvious is a poor choice, IMO. – Reed Copsey Jul 06 '10 at 17:45
  • @Sergio: I don't think that stating what "elegance" means to him is pedantry. – Adam Robinson Jul 06 '10 at 17:45
  • @Reed: Of course it's a bad idea, but that is NOT the point of this question. – Sergio Tapia Jul 06 '10 at 17:46
  • 3
    @Sergio: I guess, then, I don't see the point of the question ;) – Reed Copsey Jul 06 '10 at 17:52
  • 9
    @Sergio: if `if` ain't "baroque" don't fix it. – StriplingWarrior Jul 06 '10 at 19:03
  • It's sad that it's closed -- while it's not "fact, reference, or expertise" it still helps learning. My answer would be a bounded generic class where the Value setter throws an exception. – erict Apr 13 '15 at 16:47
  • 1
    This question should be closed and remain so. Not deleted, but it is not on-topic. – Heretic Monkey Mar 06 '18 at 15:07
  • 3
    Would be great if we could write `if (1 <= x <= 100) {}` – this.myself Mar 13 '19 at 13:20
  • 2
    the problem is that *between* is more ambiguous than two inline comparisons – Wolf May 20 '19 at 09:47
  • Elegant code, should by definition be "pleasingly ingenious and simple". Performant code that is easy to read would fall under this category. Non performant code would not be classed as ingenious as it takes too long to do what could be done. Elegance is a mix of simplicity, style and performance. – Aran Mulholland Jun 04 '19 at 04:24
  • 1
    i swear if this question was asked today it would have got many dislikes – Macindows Jul 19 '21 at 16:19

35 Answers35

209

There are a lot of options:

int x = 30;
if (Enumerable.Range(1,100).Contains(x))  //true

And indeed basic if more elegantly can be written with reversing order in the first check:

if (1 <= x && x <= 100)   //true

Also, check out this SO post for regex options.

Notes:

  • LINQ solution is strictly for style points - since Contains iterates over all items its complexity is O(range_size) and not O(1) normally expected from a range check.
    More generic version for other ranges (notice that second argument is count, not end):

    if (Enumerable.Range(start, end - start + 1).Contains(x)
    
  • There is temptation to write if solution without && like 1 <= x <= 100 - that look really elegant, but in C# leads to a syntax error "Operator '<=' cannot be applied to operands of type 'bool' and 'int'"

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
Dustin Laine
  • 37,935
  • 10
  • 86
  • 125
  • 443
    Enumerable.Range has to generate the enumerable of integers first, and then loop over each item to find it. That's a terrible idea and performance compared to checking a value is drastically different. I think we should adopt a moto, just because LINQ Extensions are cool, doesn't mean they should be used for everything. – Matthew Abbott Jul 06 '10 at 17:45
  • 17
    @Matthew: http://stackoverflow.com/questions/777400/what-is-the-biggest-mistake-people-make-when-starting-to-use-linq/777412#777412 – Adam Robinson Jul 06 '10 at 17:47
  • 18
    I agree this is a terrible idea performance-wise, but the OP wants something more fancy than an `if` statement. This certainly accomplishes that... ;) – Tim Coker Jul 06 '10 at 17:49
  • 3
    The point of this question wasn't to debate what way is faster during execution. It was what code looks nicer and still gets the job done (again: I don't care about performance); this one wins by far. Easy to read and simple to use. – Sergio Tapia Jul 06 '10 at 19:15
  • 13
    It's worth to note that the second parameter isn't "stop", but "count". So for instance, Enumerable.Range(150, 300).Contains(400) will return true. – Shathur Jul 01 '13 at 12:46
  • 3
    It's not elegant, and super slow. -1 – apocalypse Oct 01 '14 at 07:13
  • 3
    this is an appalling solution **which is not elegant**. of course, the elegant solution is a category .. an extension .. as in Tony's answer. this is the elegant way to code this type of issue in c# and most languages. – Fattie Apr 01 '15 at 03:34
  • 1
    I believe the solution with enumerable is actually **wrong** :) Well it **is working**, but it is misuse of the enumerable concept, so there should be **really important reason** to write like that - so it could be ok in some rare cases, but then context needs to be explained. – rudyryk Jul 01 '15 at 19:49
  • 2
    Easier to read?! `if(x >= 1 && x <= 100)` is much more obvious than trying to puzzle out what the first one says. – Mateen Ulhaq Jan 19 '16 at 21:38
  • 1
    `Enumerable.Range()` has the worst performance. More efficient will be `x >= min && x <= max` – Jaider Feb 01 '16 at 16:30
  • 2
    Easier to read, for "in the range", `(1 <= x && x <= 100)`, and for "out of the range" `(x < 1 && 100 < x)`. – hector-j-rivas Sep 13 '16 at 19:07
  • 14
    *Please don't use this answer*. It will have horrendous performance if your ranges are quite large. Please see the answer by @olivier-jacot-descombes – Aaron Hudon Oct 20 '16 at 19:16
  • I'm a fan of the readable orientation, but "out of the range" should use an 'or' operator: (x < 1 || 100 < x) – jaybro Dec 31 '20 at 17:49
  • I could swear that I've seen something new in C# 8 or maybe 9 about the interval checking. It was something like `if(x between a and b)` or possibly `if(x in a and b)` but I can't find it it. Was it only my mind wishing stuff?! – Konrad Viltersten Jul 07 '21 at 04:41
  • lol if you guys are going to say never use this cus performance sucks then i would argue you should just never use Linq, there are very few situations where it performs better then writing the loop yourself. Plus you dont know what the app is for, maybe a its a code beauty contest, perfectly applicable in that situation (well... not if i was a judge but you know what i mean). – Dylan R Sep 14 '21 at 18:15
  • @konrad probably `x is > 0 and < 101` etc – Caius Jard Oct 12 '21 at 03:57
  • @DylanR but there are many situations that performance of linq is on par with classic loops, and it vastly reduces code clutter which is why we use it. The compliants about this answer are well justified; it's not elegant to generate a sequence of a hundred/thousand/million etc ints and then loop through them looking for an int when a simple "greater than less than" pair will do. It's not particularly readable/glanceable, and it doesn't even work for non integers. The Range part is a terrible suggestion with no redeeming features, and I'm appalled it's become the highest voted solution – Caius Jard Oct 12 '21 at 04:01
  • @AlexeiLevenkov I believe you may have introduced an error into the answer, by claiming that Contains enumerates the full range before returning an answer. All resources I can find state that Contains gives up as soon as a matching element is found. Do you have a source for the implication that it always runs to O(n), n being the range count? – Caius Jard Oct 12 '21 at 04:09
  • @CaiusJard the time complexity of IEnumerable.Contains() is O(number_of_elements_in_enumerable) irrespective whether it stops as soon as it finds element (behavior of all code in practice) or goes to the end of the enumerable always (which has to happen for all "not found" cases anyway). Indeed, I probably could write some longer explanation of exact behavior but I don't have a good (and more importantly short) way to explain that. I'm ok if you (or anyone) revert this change as completely wrong, it served its purpose of being duplicate target and I don't particularly care about it. – Alexei Levenkov Oct 12 '21 at 04:27
  • Ok, I think we are saying the same thing just in different ways. I'm taking `n` to be the maximum number of elements possible in the enumerable (ie the count passed to Range), you're taking it as the number of elements enumerated by Contains (which will be less than the maximum if the element is found, ie if it's Range(1,100).Contains(50) then 50 comparisons will be made) – Caius Jard Oct 12 '21 at 05:03
  • @CaiusJard Yeah, I think it's that syntax. What is the formal name of it so I can remember it and google for it when I forget? – Konrad Viltersten Oct 12 '21 at 10:28
  • Hah, there are so many variations I don't even know what I'd call it - "combinatored logical pattern matched pattern" maybe.. "pattern matching" is a big catchall https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/functional/pattern-matching – Caius Jard Oct 12 '21 at 10:33
145
  1. In production code I would simply write

    1 <= x && x <= 100

    This is easy to understand and very readable.

  2. Starting with C#9.0 we can write

    x is >= 1 and <= 100
    

    Note that we must write x only once. is introduces a pattern matching expression where and is part of the pattern. && would require us to repeat x is as in x is >= 1 && x is <= 100

  3. Here is a clever method that reduces the number of comparisons from two to one by using some math. There is not necessarily a performance advantage in doing so, but it is elegant. The idea is that one of the two factors becomes negative if the number lies outside of the range and zero if the number is equal to one of the bounds:

    If the bounds are inclusive:

    (x - 1) * (100 - x) >= 0
    

    or

    (x - min) * (max - x) >= 0
    

    If the bounds are exclusive:

     (x - 1) * (100 - x) > 0
    

    or

    (x - min) * (max - x) > 0
    
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • 4
    By my standards this by far the most elegant solution, interesting is that for me it also seems to run somewhat faster than checking the both of the expressions, that said it also seems more inconsistent (speed seems to vary more) would be interesting to see if there's any research done on which one is the faster. – Thomas Lindvall Mar 18 '15 at 19:34
  • The problem when executing code that has conditional jumps (if-else and loop statements or shortcut evaluation of Boolean expressions) is, that the microprocessor might have to flush the execution pipeline depending on the outcome of a condition. Modern microprocessors have several integer and floating point units allowing them to perform operations in parallel (like the two subtractions). This can explain the faster speed of my arithmetical approach. – Olivier Jacot-Descombes Mar 18 '15 at 21:10
  • 3
    Tested your solution on javascript and its accurate with floating-point numbers up to 14 decimals. It's a very good code snippet. It'd upvote you thrice if I could – rubbyrubber Dec 29 '15 at 23:32
  • 6
    Though, there is a minor issue if large positive numbers are involved, it can overflow! XD You might want to keep that in mind when writing your code. – BrainStorm.exe Feb 08 '16 at 19:56
  • 3
    The question asks for elegance and is therefore more of academic than of practical value. Personally I would just use a simple `1 < x && x < 100` in productive code. Its easier to understand. – Olivier Jacot-Descombes Jun 01 '16 at 15:14
  • 6
    For those concerned about performance, `1 < x & x < 100` (no && short circuit) instructs the compiler that it can always evaluate `x < 100` no matter the result of `1 < x`. Strangely (due to branch prediction) it is faster to always do this simple operation than it is to sometimes skip it. – Tom Leys Dec 07 '17 at 02:23
  • 2
    Branch prediction is only useful when using short-circuit `&&` evaluation, as `&` does not involve a branch. – Olivier Jacot-Descombes Dec 07 '17 at 13:26
  • This was asked in 2013? So C# 9 wasn't really on the horizon just yet... – C. Sederqvist May 21 '21 at 19:25
  • 1
    @cseder, I answered in 2013 as well, but I try to keep my answers up to date. – Olivier Jacot-Descombes May 24 '21 at 09:13
  • Although the C#9.0 solution is academic for me right now, it might be useful to specify whether or not this has the same advantage of your original answer of "running faster" by avoiding branches. I could probably look up the announcement of this functionality, and find out whether the standard specifies whether this `and` works like `&&` (explicitly avoiding evaluation of later comparisons if they have side-effects) or like `&` (always evaluating all expressions whether or not 'needed') or indeed "non-deterministic" (any expression may be evaluated or not depending on other optimisations) – Steve Jun 10 '21 at 08:38
  • Apart from the order there is no difference. See: https://sharplab.io/#v2:CYLg1APgAgTAjAWAFBQMwAJboMLoN7LpGYYBGA9uQDboCycAFAJYB2ALugB4CU+hxAitXSl0AXnRx0AHgmd0AMgVcZEuAAZ1Abn4CiUAOwidSAQF9kukiMo1aMZuy68CpvUSE1Rc9EwDO6AB8augAhizAqpKaJu76RqSxxBZIZkA – Olivier Jacot-Descombes Jun 10 '21 at 12:16
  • There is an error in your logic for `min > max`. You have given an algorithm for `XAND` instead of `AND`. – Mark Jul 10 '21 at 05:15
  • @Mark. I assume that `min <=max`. You must check this and throw an exception or handle it in another way, if this assumption can be violated. – Olivier Jacot-Descombes Jul 10 '21 at 15:58
  • @OlivierJacot-Descombes You can of course compare min to max, but then you don't "reduce the number of comparisons from two to one" unless you're checking against the same bounds multiple times. – Mark Jul 11 '21 at 03:16
  • 1
    @Mark, min > max is a pathological case which will not occur in most cases, since the boundaries are often given as constants. If they are given as a user input, then testing this input is another task than testing the range. – Olivier Jacot-Descombes Jul 11 '21 at 14:28
115

Do you mean?

if(number >= 1 && number <= 100)

or

bool TestRange (int numberToCheck, int bottom, int top)
{
  return (numberToCheck >= bottom && numberToCheck <= top);
}
Liam Laverty
  • 152
  • 2
  • 9
kemiller2002
  • 113,795
  • 27
  • 197
  • 251
  • 1
    You don't need "is" in there... This won't compile. (Otherwise, I agree 100%) – Reed Copsey Jul 06 '10 at 17:34
  • 4
    @Ben, just wait until I try and patent it too :) – kemiller2002 Jul 06 '10 at 17:38
  • 1
    I think this is the most solid solution but not that elegantly the questioner looking for, isn't ? – Kevin Simple May 27 '15 at 04:40
  • 1
    The only thing I would change is to add the static keyword to the method. ;-) – Robert S. Jun 17 '16 at 21:42
  • 1
    Needs boundary flags, i.e. InRange(number, lowerBound, LOWER_IS_INCLUSIVE , Upperbound, UPPER_IS_EXCLUSIVE) to allow for < vs <=. I wrote this intending to be snarky but now that I think about it the flags would actually encourage the caller to get their specification straight. – William T. Mallard Jul 27 '16 at 08:08
  • You could do that, or the caller could adjust the range passed in. By adding flags, the method becomes much more complicated, because you must account for the different scenarios (upper is inclusive and lower is not, both upper and lower are not inclusive, etc.) and must have many more tests to validate the method works. It also makes it more complicated for the caller, and other people reading the code. By setting the rule that it's always inclusive, anyone calling the method will know exactly how it works. – kemiller2002 Jul 27 '16 at 10:28
76

Just to add to the noise here, you could create an extension method:

public static bool IsWithin(this int value, int minimum, int maximum)
{
    return value >= minimum && value <= maximum;
}

Which would let you do something like...

int val = 15;

bool foo = val.IsWithin(5,20);

That being said, this seems like a silly thing to do when the check itself is only one line.

Adam Robinson
  • 182,639
  • 35
  • 285
  • 343
  • 1
    @Ben: I went on the subject, which says "within a range" (which I don't think is ambiguous in that regard), but you're right in that the question body says "between 1 and 100" (which is, of course, ambiguous). – Adam Robinson Jul 06 '10 at 17:44
51

As others said, use a simple if.

You should think about the ordering.

e.g

1 <= x && x <= 100

is easier to read than

x >= 1 && x <= 100
Marshal
  • 6,551
  • 13
  • 55
  • 91
Esben Skov Pedersen
  • 4,437
  • 2
  • 32
  • 46
  • 28
    "Easier" is in the eye of the beholder. I personally prefer to have the variable in question on the left and the constant or variable *not* in question on the right. – Adam Robinson Jul 06 '10 at 18:25
  • 16
    In [Perl 6](http://dev.perl.org/perl6/rfc/25.html), you would write `1 <= x <= 100`. – Jordão Jul 06 '10 at 18:46
  • @Adam: Steve McConnell agrees with EsbenP that "number line" order is clearest (in Code Complete). Personally I agree with you. I suspect that's because I've been using that form for many years now. – MarkJ Jul 06 '10 at 19:18
  • I up-voted Kevin's answer, but then I saw this. Great answer. – CaptainCasey Jul 07 '10 at 01:34
  • 3
    Number line order is the clearest initially - but you can train your eyes/mind for other orders. Specifically - I like the trick of placing the _constant_ on the left, always. If you do that the compiler will tell you when you've typed `=` instead of `==`. It doesn't help with non-equality relational operators - but it is easy to get used to using it consistently. – davidbak Mar 22 '16 at 21:31
  • 1
    I just want to add that this solution is not useful in any case. Consider `x` is a complex function call or time-consuming Linq-expression. In this case you would do this twice which isn't a good thing. Sure you should store the value into a temporary local variable but there are some cases (e.g. in else-if-statements) where you only want to call the functions after other if's or else-if's failed. With temporary variables you have to call them anyway before. An extension method (mentioned in other answers) is the best solution imho in those cases. – Robert S. Jun 17 '16 at 21:39
  • 5
    I like number line order too, and also for the complement test, e.g. x < 10 || 20 < x. To me it shouts "x is outside the range 10 - 20". – William T. Mallard Jul 27 '16 at 08:12
  • @AdamRobinson I read that rule from a best practices book. But, that rule doesn't apply here. There are always exceptions. I don't believe that you "personally prefer", as it's definitely uncomfortable when number is on the left in this context. – unobatbayar Dec 23 '21 at 02:03
31

I propose this:

public static bool IsWithin<T>(this T value, T minimum, T maximum) where T : IComparable<T> {
    if (value.CompareTo(minimum) < 0)
       return false;
    if (value.CompareTo(maximum) > 0)
       return false;
    return true;
}

Examples:

45.IsWithin(32, 89)
true
87.2.IsWithin(87.1, 87.15)
false
87.2.IsWithin(87.1, 87.25)
true

and of course with variables:

myvalue.IsWithin(min, max)

It's easy to read (close to human language) and works with any comparable type (integer, double, custom types...).

Having code easy to read is important because the developer will not waste "brain cycles" to understand it. In long coding sessions wasted brain cycles make developer tired earlier and prone to bug.

Anton M
  • 798
  • 7
  • 17
  • 4
    i would simplify even more by using the word between, and having a boolean flag to determine if inclusive or not – Ben Apr 13 '17 at 16:58
  • 1
    Good. It is easy to understand. I changed the name `IsInRange. I'm not that keen on Ben's inclusive boolean as that requires a few more brain cycles. It has the advantage that it can be used in any class that that implements IComparer. This is in my Extensions now along with `LiesWithin / `LiesInside. Just can't decide which. `NotOutside would work but I don't like negative conditions – Paulustrious Oct 02 '17 at 19:03
  • 1
    This is a much more concise version of this logic: `public static bool Between(this T value, T min, T max) where T : IComparable => value.CompareTo(min) >= 0 && value.CompareTo(max) <= 0;` – Neo Nov 06 '20 at 23:23
  • what this way named? – Hosserin Ibrahim Aug 30 '22 at 06:32
22

With a bit of extension method abuse, we can get the following "elegant" solution:

using System;

namespace Elegant {
    public class Range {
        public int Lower { get; set; }
        public int Upper { get; set; }
    }

    public static class Ext {
        public static Range To(this int lower, int upper) {
            return new Range { Lower = lower, Upper = upper };
        }

        public static bool In(this int n, Range r) {
            return n >= r.Lower && n <= r.Upper;
        }
    }

    class Program {
        static void Main() {
            int x = 55;
            if (x.In(1.To(100)))
                Console.WriteLine("it's in range! elegantly!");
        }
    }
}
Ferruccio
  • 98,941
  • 38
  • 226
  • 299
  • Like the solution! Btw to support inclusive, create `enum Inclusive` with values: `Lower`, `Upper`, `All`. And pass for the `In` function one additional parameter of type `enum Inclusive` with default value `Inclusive.All`, update the `To` function body to handle `All`, `Lower`, `Upper` values :) – Nikita Jul 31 '19 at 10:05
8

If this is incidental, a simple if is all you need. If this happens in many places, you might want to consider these two:

  • PostSharp. Decorate methods with attributes that 'inject' code into the method after compilation. I don't know for sure, but I can imagine it can be used for this.

Something like:

[Between("parameter", 0, 100)]
public void Foo(int parameter)
{
}
  • Code contracts. Has the advantage that the constraints can be checked at compile time, by static verification of your code and the places that use your code.
JulianR
  • 16,213
  • 5
  • 55
  • 85
  • +1 for code contracts; it's specific to validating a parameter, but it's a frequent use case and static verification has the potential to be extremely useful. – Dan Bryant Jul 06 '10 at 18:32
7

EDIT: New Answer provided. I was just starting out using C# when I wrote the first answer to this question, and in hindsight I now realize that my "solution" was / is naive and inefficient.

My original answer: I'd go with the more simple version:

`if(Enumerable.Range(1,100).Contains(intInQuestion)) { ...DoStuff; }`

A Better Way

As I haven't seen any other solution that is more efficient (according to my tests at least), I'll give it another go.

New and better way that also works with negative ranges:

// Returns true if x is in range [min..max], else false 
bool inRange(int x, int min=1, int max=100) => ((x - max)*(x - min) <= 0);

This can be used with both positive and negative ranges and defaults to a range of

1..100 (inclusive) and uses x as the number to check followed by an optional range defined by min and max.

Adding Examples For Good Measure

Example 1:

// Returns true if x is in range [min..max], else false 
bool inRange(int x, int min=1, int max=100) => ((x - max)*(x - min) <= 0);

Console.WriteLine(inRange(25));
Console.WriteLine(inRange(1));
Console.WriteLine(inRange(100));
Console.WriteLine(inRange(25, 30, 150));
Console.WriteLine(inRange(-25, -50, 0));

Returns:

True
True
True
False
True

Example 2: Using a list of 100000 random ints between 1 and 150

// Returns true if x is in range [min..max], else false 
bool inRange(int x, int min=1, int max=100) => ((x - max)*(x - min) <= 0);

// Generate 100000 ints between 1 and 150
var intsToCheck = new List<int>();
var randGen = new Random();
for(int i = 0; i < 100000; ++i){
    intsToCheck.Add(randGen.Next(150) + 1);
}

var counter = 0;
foreach(int n in intsToCheck) {
    if(inRange(n)) ++counter;
}

Console.WriteLine("{0} ints found in range 1..100", counter);

Returns:

66660 ints found in range 1..100

Execution Time: 0.016 second(s)
C. Sederqvist
  • 2,830
  • 19
  • 27
  • Yeay, I’m commenting on a comment to my answer from 2013 :) @RyanTheLeach : How is my answer to this question different from the now “accepted” answer? I realize that it isn’t the most effective traversal, but “terrible”? How bad can allocating and looping through 100 ints be? In 1950 it was probably not socially accepted, but... – C. Sederqvist Feb 12 '20 at 23:19
  • @RyanTheLeach I don't blame you... I've updated my answer, so, if you know about a solution that is even more efficient, please elaborate! – C. Sederqvist Feb 17 '20 at 20:31
  • 1
    I've deleted my comments as they no longer stand. Thanks for the fix, it seems ok. – Ryan Leach Feb 18 '20 at 05:05
  • 1
    Considering the question, this solution seems to be the more elegant one. Simple and clean. – Jacobson Apr 27 '22 at 18:25
7
if (value > 1 && value < 100)
{
    // do work
}
else
{
    // handle outside of range logic
}
Nick Larsen
  • 18,631
  • 6
  • 67
  • 96
6

Using an && expression to join two comparisons is simply the most elegant way to do this. If you try using fancy extension methods and such, you run into the question of whether to include the upper bound, the lower bound, or both. Once you start adding additional variables or changing the extension names to indicate what is included, your code becomes longer and harder to read (for the vast majority of programmers). Furthermore, tools like Resharper will warn you if your comparison doesn't make sense (number > 100 && number < 1), which they won't do if you use a method ('i.IsBetween(100, 1)').

The only other comment I'd make is that if you're checking inputs with the intention to throw an exception, you should consider using code contracts:

Contract.Requires(number > 1 && number < 100)

This is more elegant than if(...) throw new Exception(...), and you could even get compile-time warnings if someone tries to call your method without ensuring that the number is in bounds first.

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • 2
    FYI, the contracts static analyzer is happier when the lower bound and upper bound constraints are split into separate Requires statements. – Dan Bryant Jul 06 '10 at 20:12
  • Thanks Dan Bryant, that is precisely what I was here looking for. Cannot find much material on suggestions on style of conditions for the Requires and other related Code Contract methods. – jpierson Sep 30 '13 at 01:11
3

In C, if time efficiency is crucial and integer overflows will wrap, one could do if ((unsigned)(value-min) <= (max-min)) .... If 'max' and 'min' are independent variables, the extra subtraction for (max-min) will waste time, but if that expression can be precomputed at compile time, or if it can be computed once at run-time to test many numbers against the same range, the above expression may be computed efficiently even in the case where the value is within range (if a large fraction of values will be below the valid range, it may be faster to use if ((value >= min) && (value <= max)) ... because it will exit early if value is less than min).

Before using an implementation like that, though, benchmark one one's target machine. On some processors, the two-part expression may be faster in all cases since the two comparisons may be done independently whereas in the subtract-and-compare method the subtraction has to complete before the compare can execute.

Sachin Chavan
  • 5,578
  • 5
  • 49
  • 75
supercat
  • 77,689
  • 9
  • 166
  • 211
  • And the compiler might perform this optimisation for you in release builds. Sometimes more readable code performs exactly the same. – Jeremy Lakeman Sep 22 '21 at 14:33
  • @JeremyLakeman: Sometimes it does. And when programming dekstop-level or server-level processors, compilers which understand caching and pipelining issues may be able to make better optimization decisions than programmers. When using targets which execute discrete instructions sequentially (typical in the embedded world), however, generating optimal code may require knowing the distribution of input cases in ways that a programmer might and a compiler can't. Unfortunately, C doesn't provide any means of distinguishing situations where a compiler should perform operations in the exact... – supercat Sep 22 '21 at 15:00
  • ...sequence given from those where it should substitute operations that would likely be faster for reasonably-balanced inputs. Further, the language provides no means of inviting a compiler to e.g. compute either `((long)a*b > c` or `(int)((unsigned)a*b) > c` at its leisure, without "inviting" a compiler to behave completely nonsensically in the cases where the product of `a*b` wouldn't be representable as `int`. – supercat Sep 22 '21 at 15:08
  • I like this approach when implemented as as macro. Validating the range of some variable before accessing some code where a bad value would cause something bad to happen (e.g. writing to an array) is good practice and I don't want to make assumptions about the type of variable (signed vs unsigned) so something like `x >= 0 && x < length` can make the compiler emit the annoying "comparison is always true due to limited range of data type" warning. However doing the comparison as described avoids the warning. – Peter Ball Jan 24 '23 at 01:11
3
static class ExtensionMethods
{
    internal static bool IsBetween(this double number,double bound1, double bound2)
    {
        return Math.Min(bound1, bound2) <= number && number <= Math.Max(bound2, bound1);
    }

    internal static bool IsBetween(this int number, double bound1, double bound2)
    {
        return Math.Min(bound1, bound2) <= number && number <= Math.Max(bound2, bound1);
    }
}

Usage

double numberToBeChecked = 7;

var result = numberToBeChecked.IsBetween(100,122);

var result = 5.IsBetween(100,120);

var result = 8.0.IsBetween(1.2,9.6);

3

These are some Extension methods that can help

  public static bool IsInRange<T>(this T value, T min, T max)
where T : System.IComparable<T>
    {
        return value.IsGreaterThenOrEqualTo(min) && value.IsLessThenOrEqualTo(max);
    }


    public static bool IsLessThenOrEqualTo<T>(this T value, T other)
         where T : System.IComparable<T>
    {
        var result = value.CompareTo(other);
        return result == -1 || result == 0;
    }


    public static bool IsGreaterThenOrEqualTo<T>(this T value, T other)
         where T : System.IComparable<T>
    {
        var result = value.CompareTo(other);
        return result == 1 || result == 0;
    }
hanan
  • 1,768
  • 1
  • 14
  • 19
3

You can use pattern matching to achieve this in the most elegant way:

int i = 5;
if(i is (>0 and <=10))
{

}
aydjay
  • 858
  • 11
  • 25
3

Using the built in Range struct (C# 8+), we can create an extension method to check if an Index is within the original range.

public static bool IsInRangeOf(this Range range, Index index)
{
   return index.Value >= range.Start.Value && index.Value < range.End.Value;
}

Since Index overrides the implicit operator, we can pass an int instead of an Index struct.

var range = new Range(1, 10);
var isInRange = range.IsInRangeOf(1); // true, 1..10 is inclusive min range index(1)
var isInRange = range.IsInRangeOf(10); // false, 1..10 exclusive on max range index (10).
var isInRange = range.IsInRangeOf(100); // false

Reap
  • 1,047
  • 13
  • 16
3

Ok I'll play along. So many answers already but maybe still room for some other novelties:

(obviously don't actually use these)

    var num = 7;
    const int min = 5;
    const int max = 10;
    var inRange = Math.Clamp(num, min, max) == num;

Or

    var num = 7;
    const int min = 5;
    const int max = 10;
    var inRange = num switch { < min => false, > max => false, _ => true };

Or

    var num = 7;
    const int min = 5;
    const int max = 10;
    var inRange = num is >= min and <= max;

OK maybe you could use that last one.

OK one more

    var num = 7;
    const int min = 5;
    const int max = 10;
    var inRange = Enumerable.Range(min, max-min).Contains(num);
herostwist
  • 3,778
  • 1
  • 26
  • 34
  • Thanks for teaching me about Math.Clamp()! The pattern matching ones do not work if either of min and max is not a constant -- your code works, but drawing the reader's attention to the const-ness in prose might help get the message across. – Palec Jun 22 '22 at 13:14
2

If you want to write more code than a simple if, maybe you can: Create a Extension Method called IsBetween

public static class NumberExtensionMethods
{
    public static bool IsBetween(this long value, long Min, long Max)
    {
        // return (value >= Min && value <= Max);
        if (value >= Min && value <= Max) return true;
        else return false;
    }
}

...

// Checks if this number is between 1 and 100.
long MyNumber = 99;
MessageBox.Show(MyNumber.IsBetween(1, 100).ToString());

Addendum: it's worth noting that in practice you very rarely "just check for equality" (or <, >) in a codebase. (Other than in the most trivial situations.) Purely as an example, any game programmer would use categories something like the following in every project, as a basic matter. Note that in this example it (happens to be) using a function (Mathf.Approximately) which is built in to that environment; in practice you typically have to carefully develop your own concepts of what comparisons means for computer representations of real numbers, for the type of situation you are engineering. (Don't even mention that if you're doing something like, perhaps a controller, a PID controller or the like, the whole issue becomes central and very difficult, it becomes the nature of the project.) BY no means is the OP question here a trivial or unimportant question.

private bool FloatLessThan(float a, float b)
    {
    if ( Mathf.Approximately(a,b) ) return false;
    if (a<b) return true;
    return false;
    }

private bool FloatLessThanZero(float a)
    {
    if ( Mathf.Approximately(a,0f) ) return false;
    if (a<0f) return true;
    return false;
    }

private bool FloatLessThanOrEqualToZero(float a)
    {
    if ( Mathf.Approximately(a,0f) ) return true;
    if (a<0f) return true;
    return false;
    }
Fattie
  • 27,874
  • 70
  • 431
  • 719
Tony
  • 16,527
  • 15
  • 80
  • 134
  • 1
    Replace the if and else with `return (value >= Min && value <= Max);` – AeroX Nov 27 '14 at 14:20
  • the elegant way to write the comparison is "in logical order..." if ( Min <= value && value <= Max ). That is much prettier. – Fattie Apr 01 '15 at 03:35
  • 2
    Further on this question, it's so surprising that nobody has mentioned the central issue in any real-world project (particularly if you're a game engineer) **is that you have to deal with the approximation issue**. In any real-world software you essentially never "just do a comparison" (whether equality or <, >) you have to consider and deal with the error issue, depending on the situation at hand. I've edited in an addendum to this answer (the only correct answer here!) since no more answers are allowed. – Fattie Apr 02 '15 at 04:32
  • Thank you for this observation and the addendum. – Tony Apr 02 '15 at 12:43
2

Cause all the other answer are not invented by me, here just my implementation:

public enum Range
{
    /// <summary>
    /// A range that contains all values greater than start and less than end.
    /// </summary>
    Open,
    /// <summary>
    /// A range that contains all values greater than or equal to start and less than or equal to end.
    /// </summary>
    Closed,
    /// <summary>
    /// A range that contains all values greater than or equal to start and less than end.
    /// </summary>
    OpenClosed,
    /// <summary>
    /// A range that contains all values greater than start and less than or equal to end.
    /// </summary>
    ClosedOpen
}

public static class RangeExtensions
{
    /// <summary>
    /// Checks if a value is within a range that contains all values greater than start and less than or equal to end.
    /// </summary>
    /// <param name="value">The value that should be checked.</param>
    /// <param name="start">The first value of the range to be checked.</param>
    /// <param name="end">The last value of the range to be checked.</param>
    /// <returns><c>True</c> if the value is greater than start and less than or equal to end, otherwise <c>false</c>.</returns>
    public static bool IsWithin<T>(this T value, T start, T end) where T : IComparable<T>
    {
        return IsWithin(value, start, end, Range.ClosedOpen);
    }

    /// <summary>
    /// Checks if a value is within the given range.
    /// </summary>
    /// <param name="value">The value that should be checked.</param>
    /// <param name="start">The first value of the range to be checked.</param>
    /// <param name="end">The last value of the range to be checked.</param>
    /// <param name="range">The kind of range that should be checked. Depending on the given kind of range the start end end value are either inclusive or exclusive.</param>
    /// <returns><c>True</c> if the value is within the given range, otherwise <c>false</c>.</returns>
    public static bool IsWithin<T>(this T value, T start, T end, Range range) where T : IComparable<T>
    {
        if (value == null)
            throw new ArgumentNullException(nameof(value));

        if (start == null)
            throw new ArgumentNullException(nameof(start));

        if (end == null)
            throw new ArgumentNullException(nameof(end));

        switch (range)
        {
            case Range.Open:
                return value.CompareTo(start) > 0
                       && value.CompareTo(end) < 0;
            case Range.Closed:
                return value.CompareTo(start) >= 0
                       && value.CompareTo(end) <= 0;
            case Range.OpenClosed:
                return value.CompareTo(start) > 0
                       && value.CompareTo(end) <= 0;
            case Range.ClosedOpen:
                return value.CompareTo(start) >= 0
                       && value.CompareTo(end) < 0;
            default:
                throw new ArgumentException($"Unknown parameter value {range}.", nameof(range));
        }
    }
}

You can then use it like this:

var value = 5;
var start = 1;
var end = 10;

var result = value.IsWithin(start, end, Range.Closed);
Oliver
  • 43,366
  • 8
  • 94
  • 151
1

I would do a Range object, something like this:

public class Range<T> where T : IComparable
{
    public T InferiorBoundary{get;private set;}
    public T SuperiorBoundary{get;private set;}

    public Range(T inferiorBoundary, T superiorBoundary)
    {
        InferiorBoundary = inferiorBoundary;
        SuperiorBoundary = superiorBoundary;
    }

    public bool IsWithinBoundaries(T value){
        return InferiorBoundary.CompareTo(value) > 0 && SuperiorBoundary.CompareTo(value) < 0;
    }
}

Then you use it this way:

Range<int> myRange = new Range<int>(1,999);
bool isWithinRange = myRange.IsWithinBoundaries(3);

That way you can reuse it for another type.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
IEatBagels
  • 823
  • 2
  • 8
  • 23
  • Your `Range` object needs to use the `CompareTo` method to compare items, not the `<` operator. – Servy Sep 20 '13 at 16:06
  • You're right, though if implementing IComparable you should also override operators (at least that's what my VS code analysis is saying), meaning < would work. Although I might be wrong, I don't have much experience and this is my first answer on SO – IEatBagels Sep 20 '13 at 17:27
  • No, your compiler *won't* say that this works. This won't compile. It is entirely reasonable for an object to implement `IComparable` and not overload the `<` operator. – Servy Sep 20 '13 at 17:28
1

How about something like this?

if (theNumber.isBetween(low, high, IntEx.Bounds.INCLUSIVE_INCLUSIVE))
{
}

with the extension method as follows (tested):

public static class IntEx
{
    public enum Bounds 
    {
        INCLUSIVE_INCLUSIVE, 
        INCLUSIVE_EXCLUSIVE, 
        EXCLUSIVE_INCLUSIVE, 
        EXCLUSIVE_EXCLUSIVE
    }

    public static bool isBetween(this int theNumber, int low, int high, Bounds boundDef)
    {
        bool result;
        switch (boundDef)
        {
            case Bounds.INCLUSIVE_INCLUSIVE:
                result = ((low <= theNumber) && (theNumber <= high));
                break;
            case Bounds.INCLUSIVE_EXCLUSIVE:
                result = ((low <= theNumber) && (theNumber < high));
                break;
            case Bounds.EXCLUSIVE_INCLUSIVE:
                result = ((low < theNumber) && (theNumber <= high));
                break;
            case Bounds.EXCLUSIVE_EXCLUSIVE:
                result = ((low < theNumber) && (theNumber < high));
                break;
            default:
                throw new System.ArgumentException("Invalid boundary definition argument");
        }
        return result;
    }
}
William T. Mallard
  • 1,562
  • 2
  • 25
  • 33
1

A new twist on an old favorite:

public bool IsWithinRange(int number, int topOfRange, int bottomOfRange, bool includeBoundaries) {
    if (includeBoundaries)
        return number <= topOfRange && number >= bottomOfRange;
    return number < topOfRange && number > bottomOfRange;
}
Ben Hoffstein
  • 102,129
  • 8
  • 104
  • 120
1

When checking if a "Number" is in a range you have to be clear in what you mean, and what does two numbers are equal mean? In general you should wrap all floating point numbers in what is called a 'epsilon ball' this is done by picking some small value and saying if two values are this close they are the same thing.

    private double _epsilon = 10E-9;
    /// <summary>
    /// Checks if the distance between two doubles is within an epsilon.
    /// In general this should be used for determining equality between doubles.
    /// </summary>
    /// <param name="x0">The orgin of intrest</param>
    /// <param name="x"> The point of intrest</param>
    /// <param name="epsilon">The minimum distance between the points</param>
    /// <returns>Returns true iff x  in (x0-epsilon, x0+epsilon)</returns>
    public static bool IsInNeghborhood(double x0, double x, double epsilon) => Abs(x0 - x) < epsilon;

    public static bool AreEqual(double v0, double v1) => IsInNeghborhood(v0, v1, _epsilon);

With these two helpers in place and assuming that if any number can be cast as a double without the required accuracy. All you will need now is an enum and another method

    public enum BoundType
    {
        Open,
        Closed,
        OpenClosed,
        ClosedOpen
    }

The other method follows:

    public static bool InRange(double value, double upperBound, double lowerBound, BoundType bound = BoundType.Open)
    {
        bool inside = value < upperBound && value > lowerBound;
        switch (bound)
        {
            case BoundType.Open:
                return inside;
            case BoundType.Closed:
                return inside || AreEqual(value, upperBound) || AreEqual(value, lowerBound); 
            case BoundType.OpenClosed:
                return inside || AreEqual(value, upperBound);
            case BoundType.ClosedOpen:
                return inside || AreEqual(value, lowerBound);
            default:
                throw new System.NotImplementedException("You forgot to do something");
        }
    }

Now this may be far more than what you wanted, but it keeps you from dealing with rounding all the time and trying to remember if a value has been rounded and to what place. If you need to you can easily extend this to work with any epsilon and to allow your epsilon to change.

rahicks
  • 573
  • 7
  • 19
1

Elegant because it doesn't require you to determine which of the two boundary values is greater first. It also contains no branches.

public static bool InRange(float val, float a, float b)
{
    // Determine if val lies between a and b without first asking which is larger (a or b)
    return ( a <= val & val < b ) | ( b <= val & val < a );
}
Tom Leys
  • 18,473
  • 7
  • 40
  • 62
1

If you are concerned with the comment by @Daap on the accepted answer and can only pass the value once, you could try one of the following

bool TestRangeDistance (int numberToCheck, int bottom, int distance)
{
  return (numberToCheck >= bottom && numberToCheck <= bottom+distance);
}

//var t = TestRangeDistance(10, somelist.Count()-5, 10);

or

bool TestRangeMargin (int numberToCheck, int target, int margin)
{
  return (numberToCheck >= target-margin && numberToCheck <= target+margin);
}

//var t = TestRangeMargin(10, somelist.Count(), 5);
Hugo Delsing
  • 13,803
  • 5
  • 45
  • 72
1

Regarding elegance, the closest thing to the mathematical notation (a <= x <= b) slightly improves readability:

public static bool IsBetween(this int value, int min, int max)
{
    return min <= value && value <= max;
}

For further illustration:

public static bool IsOutside(this int value, int min, int max)
{
    return value < min || max < value;
}
hector-j-rivas
  • 771
  • 8
  • 21
0

I was looking for an elegant way to do it where the bounds might be switched (ie. not sure which order the values are in).

This will only work on newer versions of C# where the ?: exists

bool ValueWithinBounds(float val, float bounds1, float bounds2)
{
    return bounds1 >= bounds2 ?
      val <= bounds1 && val >= bounds2 : 
      val <= bounds2 && val >= bounds1;
}

Obviously you could change the = signs in there for your purposes. Could get fancy with type casting too. I just needed a float return within bounds (or equal to)

0

I don't know but i use this method:

    public static Boolean isInRange(this Decimal dec, Decimal min, Decimal max, bool includesMin = true, bool includesMax = true ) {

    return (includesMin ? (dec >= min) : (dec > min)) && (includesMax ? (dec <= max) : (dec < max));
}

And this is the way I can use it:

    [TestMethod]
    public void IsIntoTheRange()
    {
        decimal dec = 54;

        Boolean result = false;

        result = dec.isInRange(50, 60); //result = True
        Assert.IsTrue(result);

        result = dec.isInRange(55, 60); //result = False
        Assert.IsFalse(result);

        result = dec.isInRange(54, 60); //result = True
        Assert.IsTrue(result);

        result = dec.isInRange(54, 60, false); //result = False
        Assert.IsFalse(result);

        result = dec.isInRange(32, 54, false, false);//result = False
        Assert.IsFalse(result);

        result = dec.isInRange(32, 54, false);//result = True
        Assert.IsTrue(result);
    }
0

If it's to validate method parameters, none of the solutions throw ArgumentOutOfRangeException and allow easy/proper configuration of inclusive/exclusive min/max values.

Use like this

public void Start(int pos)
{
    pos.CheckRange(nameof(pos), min: 0);

    if (pos.IsInRange(max: 100, maxInclusive: false))
    {
        // ...
    }
}

I just wrote these beautiful functions. It also has the advantage of having no branching (a single if) for valid values. The hardest part is to craft the proper exception messages.

/// <summary>
/// Returns whether specified value is in valid range.
/// </summary>
/// <typeparam name="T">The type of data to validate.</typeparam>
/// <param name="value">The value to validate.</param>
/// <param name="min">The minimum valid value.</param>
/// <param name="minInclusive">Whether the minimum value is valid.</param>
/// <param name="max">The maximum valid value.</param>
/// <param name="maxInclusive">Whether the maximum value is valid.</param>
/// <returns>Whether the value is within range.</returns>
public static bool IsInRange<T>(this T value, T? min = null, bool minInclusive = true, T? max = null, bool maxInclusive = true)
    where T : struct, IComparable<T>
{
    var minValid = min == null || (minInclusive && value.CompareTo(min.Value) >= 0) || (!minInclusive && value.CompareTo(min.Value) > 0);
    var maxValid = max == null || (maxInclusive && value.CompareTo(max.Value) <= 0) || (!maxInclusive && value.CompareTo(max.Value) < 0);
    return minValid && maxValid;
}

/// <summary>
/// Validates whether specified value is in valid range, and throws an exception if out of range.
/// </summary>
/// <typeparam name="T">The type of data to validate.</typeparam>
/// <param name="value">The value to validate.</param>
/// <param name="name">The name of the parameter.</param>
/// <param name="min">The minimum valid value.</param>
/// <param name="minInclusive">Whether the minimum value is valid.</param>
/// <param name="max">The maximum valid value.</param>
/// <param name="maxInclusive">Whether the maximum value is valid.</param>
/// <returns>The value if valid.</returns>
public static T CheckRange<T>(this T value, string name, T? min = null, bool minInclusive = true, T? max = null, bool maxInclusive = true)
where T : struct, IComparable<T>
{
    if (!value.IsInRange(min, minInclusive, max, maxInclusive))
    {
        if (min.HasValue && minInclusive && max.HasValue && maxInclusive)
        {
            var message = "{0} must be between {1} and {2}.";
            throw new ArgumentOutOfRangeException(name, value, message.FormatInvariant(name, min, max));
        }
        else
        {
            var messageMin = min.HasValue ? GetOpText(true, minInclusive).FormatInvariant(min) : null;
            var messageMax = max.HasValue ? GetOpText(false, maxInclusive).FormatInvariant(max) : null;
            var message = (messageMin != null && messageMax != null) ?
                "{0} must be {1} and {2}." :
                "{0} must be {1}.";
            throw new ArgumentOutOfRangeException(name, value, message.FormatInvariant(name, messageMin ?? messageMax, messageMax));
        }
    }
    return value;
}

private static string GetOpText(bool greaterThan, bool inclusive)
{
    return (greaterThan && inclusive) ? "greater than or equal to {0}" :
        greaterThan ? "greater than {0}" :
        inclusive ? "less than or equal to {0}" :
        "less than {0}";
}

public static string FormatInvariant(this string format, params object?[] args) => string.Format(CultureInfo.InvariantCulture, format, args);
Etienne Charland
  • 3,424
  • 5
  • 28
  • 58
0

In C#, the optimal solution with regards to speed and codegen, with only one comparison, no bound checks and not error prone due to overflow is the following:

public static bool IsInRange(int value, int min, int max) => (uint)(value - min) <= (uint)(max - min);

Minimum and maximum value are inclusive.

Oliver
  • 926
  • 2
  • 12
  • 31
0

Using pattern matching can provide 'elegant' code, especially for complex and multiple number range checks. For example:

//complex and multiple range checks
var res = num switch {
   >=11 and <=21 => true, 
   >=43 and <=33 => true,  
   >=67 and <=72 => true,
   _ => false};

//simple one range check, not so elegant!
bool res = num switch { >=11 and <=21 => true, _ => false};

This adds to the answers already provided.

Rax
  • 665
  • 8
  • 19
0

With C# 8 and the new System.Range struct there is one more new option that utilizes the new .. operator and hasn't been mentioned yet.


First create an extension for it:

using System;

public static class RangeExtensions
{
    public static bool Contains(this Range range, int value) => range.Start.Value <= value && value < range.End.Value;
}

Then you can apply it to the Range itself:

var isInRange = (1..11).Contains(2);
t3chb0t
  • 16,340
  • 13
  • 78
  • 118
-1

I use next 'elegant' solution:

using static System.Linq.Enumerable;

int x = 30;
if (Range(1,100).Contains(x))  //true

From Microsoft docs

The using static directive applies to any type that has static members (or nested types), even if it also has instance members. However, instance members can only be invoked through the type instance.

You can access static members of a type without having to qualify the access with the type name:

But this is not trivial for many people, because Enumerable.Range has first argument start and second one count. So this checking may be useful in specific situations, like when you use Enumerable.Range for the foreach loop and before start, you wanted to know, if the loop will be executed.

For example:

        int count = 100;
        int x = 30;

        if (!Range(1, count).Contains(x)) {
            Console.WriteLine("Do nothing!");
            return;
        }

        foreach (var i in Range(1, count)) {
            // Some job here
        }
Childcity
  • 19
  • 7
  • 1
    This solution has a significant memory footprint and linear time complexity given the simple problem at hand... Also just realised, the same solution has already been proposed – redspidermkv Jan 09 '22 at 14:05
  • @redspidermkv You are right! But I said "may be useful". This means for some situations this solution may have sense. Of course, for most of us the `if (1 <= x && x <= 100)` I think is the best choice :) – Childcity Jan 10 '22 at 17:25
-2

You are looking for in [1..100]? That's only Pascal.

Polluks
  • 525
  • 2
  • 8
  • 19
  • 3
    Not true, its not only Pascal. Many modern languages have features like this. In Kotlin, for example it is called "Pattern Matching". Example `when (number) { in 0..9 -> println("1 digit") in 10..99 -> println("2 digits") in 100..999 -> println("3 digits") }` – this.myself Mar 13 '19 at 13:16
-2

June, 2022

int id = 10;
if(Enumerable.Range(1, 100).Select(x => x == id).Any()) // true
The Best
  • 105
  • 1
  • 1
  • 7
  • Enumerable.Range will create a sequence with 100 elements and then perform a comparison on each element. Not the most efficient, but it works. I suggest if in a C# 8+ solution, using `System.Range`. – Reap Jun 23 '22 at 17:33