84

Google doesn't understand that "between" is the name of the function I'm looking for and returns nothing relevant.

Ex: I want to check if 5 is between 0 and 10 in only one operation

Greg
  • 23,155
  • 11
  • 57
  • 79
Mathieu
  • 4,449
  • 7
  • 41
  • 60
  • 2
    it's kinda mathematecly impossible to do it one operation... have you tried writng your own? – AK_ Feb 16 '11 at 23:00
  • 4
    The .NET libraries don't have *every* function under the sun. You still have to code some things yourself ;) – Byron Whitlock Feb 16 '11 at 23:05
  • 2
    I was curious as SQL has a BETWEEN operator too, check this out, Jon made a LINQ equivalent http://stackoverflow.com/questions/1447635/linq-between-operator – Tom Feb 16 '11 at 23:05
  • 1
    ...which doesn't have the function either... :-/ – Peter C Feb 16 '11 at 23:10
  • MySql has but not c# – Ismail Gunes Jan 15 '18 at 10:21
  • 1
    Possible duplicate of [How to elegantly check if a number is within a range?](https://stackoverflow.com/questions/3188672/how-to-elegantly-check-if-a-number-is-within-a-range) – SandhraPrakash Aug 29 '19 at 13:33
  • Hey my answer is a one liner I think you should change the correct answer to mine. – Alex Mar 01 '20 at 02:03
  • All good answers below, just adding that this seems like a great addition to the CoreLIb. Either as a `Math` method, if not something in the language itself. – Emperor Eto Dec 10 '21 at 17:56

18 Answers18

145

It isn't clear what you mean by "one operation", but no, there's no operator / framework method that I know of to determine if an item is within a range.

You could of course write an extension-method yourself. For example, here's one that assumes that the interval is closed on both end-points.

public static bool IsBetween<T>(this T item, T start, T end)
{
    return Comparer<T>.Default.Compare(item, start) >= 0
        && Comparer<T>.Default.Compare(item, end) <= 0;
}

And then use it as:

bool b = 5.IsBetween(0, 10); // true
Ani
  • 111,048
  • 26
  • 262
  • 307
  • How would this behave for types that don't implement `IComparable` or `IComparable`? – Sam Feb 04 '13 at 22:21
  • 16
    @Sam it will throw an exception but to avoid this you can add `where T : IComparable, IComparable` – WiiMaxx Aug 12 '13 at 08:24
  • This should be the accepted solution; would be easy enough to add an "inclusive" parameter as well. – System.Cats.Lol Jun 16 '14 at 17:27
  • 2
    Great job, but if you dont't need this to be inclusive, and you want that 3 to be between 5 and 2 (as well as between 2 and 5), use this : `return Comparer.Default.Compare(item, start) == -Comparer.Default.Compare(item, end);` – mathieu Jan 02 '18 at 22:49
94

No, but you can write your own:

public static bool Between(this int num, int lower, int upper, bool inclusive = false)
{
    return inclusive
        ? lower <= num && num <= upper
        : lower < num && num < upper;
}
Justin Morgan - On strike
  • 30,035
  • 12
  • 80
  • 104
35

Here's a complete class.

/// <summary>
/// An extension class for the between operation
/// name pattern IsBetweenXX where X = I -> Inclusive, X = E -> Exclusive
/// <a href="https://stackoverflow.com/a/13470099/37055"></a>
/// </summary>
public static class BetweenExtensions
{

    /// <summary>
    /// Between check <![CDATA[min <= value <= max]]> 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">the value to check</param>
    /// <param name="min">Inclusive minimum border</param>
    /// <param name="max">Inclusive maximum border</param>
    /// <returns>return true if the value is between the min & max else false</returns>
    public static bool IsBetweenII<T>(this T value, T min, T max) where T:IComparable<T>
    {
        return (min.CompareTo(value) <= 0) && (value.CompareTo(max) <= 0);
    }

    /// <summary>
    /// Between check <![CDATA[min < value <= max]]>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">the value to check</param>
    /// <param name="min">Exclusive minimum border</param>
    /// <param name="max">Inclusive maximum border</param>
    /// <returns>return true if the value is between the min & max else false</returns>
    public static bool IsBetweenEI<T>(this T value, T min, T max) where T:IComparable<T>
    {
        return (min.CompareTo(value) < 0) && (value.CompareTo(max) <= 0);
    }

    /// <summary>
    /// between check <![CDATA[min <= value < max]]>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">the value to check</param>
    /// <param name="min">Inclusive minimum border</param>
    /// <param name="max">Exclusive maximum border</param>
    /// <returns>return true if the value is between the min & max else false</returns>
    public static bool IsBetweenIE<T>(this T value, T min, T max) where T:IComparable<T>
    {
        return (min.CompareTo(value) <= 0) && (value.CompareTo(max) < 0);
    }

    /// <summary>
    /// between check <![CDATA[min < value < max]]>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">the value to check</param>
    /// <param name="min">Exclusive minimum border</param>
    /// <param name="max">Exclusive maximum border</param>
    /// <returns>return true if the value is between the min & max else false</returns>

    public static bool IsBetweenEE<T>(this T value, T min, T max) where T:IComparable<T>
    {
        return (min.CompareTo(value) < 0) && (value.CompareTo(max) < 0);
    }
}

plus some unit test code

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethodIsBeetween()
    {
        Assert.IsTrue(5.0.IsBetweenII(5.0, 5.0));
        Assert.IsFalse(5.0.IsBetweenEI(5.0, 5.0));
        Assert.IsFalse(5.0.IsBetweenIE(5.0, 5.0));
        Assert.IsFalse(5.0.IsBetweenEE(5.0, 5.0));

        Assert.IsTrue(5.0.IsBetweenII(4.9, 5.0));
        Assert.IsTrue(5.0.IsBetweenEI(4.9, 5.0));
        Assert.IsFalse(5.0.IsBetweenIE(4.9, 5.0));
        Assert.IsFalse(5.0.IsBetweenEE(4.9, 5.0));

        Assert.IsTrue(5.0.IsBetweenII(5.0, 5.1));
        Assert.IsFalse(5.0.IsBetweenEI(5.0, 5.1));
        Assert.IsTrue(5.0.IsBetweenIE(5.0, 5.1));
        Assert.IsFalse(5.0.IsBetweenEE(5.0, 5.1));

        Assert.IsTrue(5.0.IsBetweenII(4.9, 5.1));
        Assert.IsTrue(5.0.IsBetweenEI(4.9, 5.1));
        Assert.IsTrue(5.0.IsBetweenIE(4.9, 5.1));
        Assert.IsTrue(5.0.IsBetweenEE(4.9, 5.1));

        Assert.IsFalse(5.0.IsBetweenII(5.1, 4.9));
        Assert.IsFalse(5.0.IsBetweenEI(5.1, 4.9));
        Assert.IsFalse(5.0.IsBetweenIE(5.1, 4.9));
        Assert.IsFalse(5.0.IsBetweenEE(5.1, 4.9));

    }
}
j_freyre
  • 4,623
  • 2
  • 30
  • 47
Hansjörg
  • 351
  • 3
  • 2
23

Nope, you'll have to test each endpoint individually.

if ((x > 0) && (x < 10)) {
   // do stuff
}

Or if you want it to look more "betweeny", reorder the args:

if ((0 < x) && (x < 10)) {
   // do stuff
}
Daniel DiPaolo
  • 55,313
  • 14
  • 116
  • 115
19

So far, it looks like none of the answers have considered the likely possibility that dynamically, you don't know which value is the lower and upper bound. For the general case, you could create your own IsBetween method that would probably go something like:

    public bool IsBetween(double testValue, double bound1, double bound2)
    {
        return (testValue >= Math.Min(bound1,bound2) && testValue <= Math.Max(bound1,bound2));
    }
Ed G
  • 191
  • 1
  • 2
15

As of c# 9, you can do 5 is > 0 and < 10; https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9#pattern-matching-enhancements

JohnnyFun
  • 3,975
  • 2
  • 20
  • 20
11

There is no built in construct in C#/.NET, but you can easily add your own extension method for this:

public static class ExtensionsForInt32
{
    public static bool IsBetween (this int val, int low, int high)
    {
           return val > low && val < high;
    }
}

Which can be used like:

if (5.IsBetween (0, 10)) { /* Do something */ }
Pete
  • 11,313
  • 4
  • 43
  • 54
  • +1. Only caveat would be to set expectations to the consumer that the edge cases (0 and 10) are NOT inclusive. Otherwise, this is great! – p.campbell Feb 16 '11 at 23:09
  • I used a combination of this method and the one proposed by Ani. I added the IsBetween function to my extension class as a private member. Then I used public functions similar to this to expose the specific types I wanted to extend, which call to the private function. – JRodd Jun 04 '19 at 14:35
7

Except for the answer by @Ed G, all of the answers require knowing which bound is the lower and which is the upper one.

Here's a (rather non-obvious) way of doing it when you don't know which bound is which.

  /// <summary>
  /// Method to test if a value is "between" two other values, when the relative magnitude of 
  /// the two other values is not known, i.e., number1 may be larger or smaller than number2. 
  /// The range is considered to be inclusive of the lower value and exclusive of the upper 
  /// value, irrespective of which parameter (number1 or number2) is the lower or upper value. 
  /// This implies that if number1 equals number2 then the result is always false.
  /// 
  /// This was extracted from a larger function that tests if a point is in a polygon:
  /// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
  /// </summary>
  /// <param name="testValue">value to be tested for being "between" the other two numbers</param>
  /// <param name="number1">one end of the range</param>
  /// <param name="number2">the other end of the range</param>
  /// <returns>true if testValue >= lower of the two numbers and less than upper of the two numbers,
  ///          false otherwise, incl. if number1 == number2</returns>
  private static bool IsInRange(T testValue, T number1, T number2)
  {
     return (testValue <= number1) != (testValue <= number2);
  }

Note: This is NOT a generic method; it is pseudo code. The T in the above method should be replaced by a proper type, "int" or "float" or whatever. (There are ways of making this generic, but they're sufficiently messy that it's not worth while for a one-line method, at least not in most situations.)

RenniePet
  • 11,420
  • 7
  • 80
  • 106
  • 2
    programmers used to understand logic like this :) – Fattie Apr 01 '15 at 03:36
  • I realize that this is "ancient" in Internet time, but I REALLY like this solution especially since it does not require the caller to know which bound is which. – Andrew Steitz Jul 30 '15 at 16:22
  • The above sample IsInRange is close. The "testValue <= number1" needs to be >= and not <= or it will return invalid results. – C J Apr 29 '22 at 13:07
6

Wouldn't it be as simple as

0 < 5 && 5 < 10

?

So I suppose if you want a function out of it you could simply add this to a utility class:

public static bool Between(int num, int min, int max) {
    return min < num && num < max;
}
Emanuel Vintilă
  • 1,911
  • 4
  • 25
  • 35
Peter C
  • 6,219
  • 1
  • 25
  • 37
5

Generic function that is validated at compilation!

public static bool IsBetween<T>(this T item, T start, T end) where T : IComparable
{
    return item.CompareTo(start) >= 0 && item.CompareTo(end) <= 0;
}
Peter
  • 37,042
  • 39
  • 142
  • 198
2
int val_to_check = 5
bool in_range = Enumerable.Range(0, 13).Contains(val_to_check);

The second parameter is the "count" not the end or high number.

I.E.

int low_num = 0
int high_num = 12
int val_to_check = 5
bool in_range = Enumerable.Range(low_num , high_num - low_num + 1).Contains(val_to_check);

Checks if the val_to_check is between 0 and 12

johnw182
  • 1,349
  • 1
  • 16
  • 22
  • Things are gonna get gross when: `low_num = int.MinValue` and `high_num = int.MaxValue`. Nobody should be using this type of code to check if a value is between two other values. – Metro Smurf Nov 12 '21 at 15:13
2

What about

somenumber == Math.Max(0,Math.Min(10,somenumber));

returns true when somenumber is 5. returns false when somenumber is 11.

Alex
  • 552
  • 3
  • 15
  • 3
    tbh, this does nothing much different from a simple expression `x >= a && x <= b` under the hood, but adds two unnecessary function calls. – KekuSemau May 28 '21 at 08:27
1

Refer to this link. A one line solution to that question.

How to elegantly check if a number is within a range?

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

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

I know the post is pretty old, but It may help others..

Community
  • 1
  • 1
SandhraPrakash
  • 442
  • 2
  • 6
  • 15
  • 1
    If this question is a duplicate of the question you've linked here, please flag it as a duplicate with the "flag" button under the question instead of leaving an answer to that effect. If it is not a duplicate, then please leave a complete answer instead of a link-only answer. – josliber Oct 09 '15 at 04:43
0

Base @Dan J this version don't care max/min, more like sql :)

public static bool IsBetween(this decimal me, decimal a, decimal b, bool include = true)
{
    var left = Math.Min(a, b);
    var righ = Math.Max(a, b);

    return include
        ? (me >= left && me <= righ)
        : (me > left && me < righ)
    ;
}
IlPADlI
  • 1,943
  • 18
  • 22
0

Or if you want to bound the value to the interval:

public static T EnsureRange<T>(this T value, T min, T max) where T : IComparable<T>
    {
        if (value.CompareTo(min) < 0)
            return min;
        else if (value.CompareTo(max) > 0)
            return max;
        else
            return value;
    }

It is like two-sided Math.Min/Max

Dave_cz
  • 1,180
  • 10
  • 17
0

And for negatives values:

    Public Function IsBetween(Of T)(item As T, pStart As T, pEnd As T) As Boolean ' https://msdn.microsoft.com/fr-fr/library/bb384936.aspx
    Dim Deb As T = pStart
    Dim Fin As T = pEnd
    If (Comparer(Of T).Default.Compare(pStart, pEnd) > 0) Then Deb = pEnd : Fin = pStart
    Return Comparer(Of T).Default.Compare(item, Deb) >= 0 AndAlso Comparer(Of T).Default.Compare(item, Fin) <= 0
End Function
david
  • 170
  • 10
0

I don't know that function; anyway if your value is unsigned, just one operation means (val < 11)... If it is signed, I think there is no atomic way to do it because 10 is not a power of 2...

davidcm
  • 165
  • 3
  • 11
0

As @Hellfrost pointed out, it is literally nonsense to compare a number to two different numbers in "one operation", and I know of no C# operator that encapsulates this.

between = (0 < 5 && 5 < 10);

Is about the most-compact form I can think of.

You could make a somewhat "fluent"-looking method using extension (though, while amusing, I think it's overkill):

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

Use:

int x = 5;
bool b = x.Between(0,10);
Dan J
  • 16,319
  • 7
  • 50
  • 82