开发者

How to force a number to be in a range in C#? [duplicate]

This question already has answers here: Where can I find the "clamp" function in .NET? (11 answers) Closed 6 years ago.

In C#, I often have to limit an integer value to a range of values. For example, if an application expects a percentage, an integer from a user input must not be less than zero or more than one hundred. Another example: if there are five web pages which are accessed through Request.Params["p"], I expect a value from 1 to 5, not 0 or 256 or 99999.

I often end by writing a quite ugly code like:

page = Math.Max(0, Math.Min(2, page));

or even uglier:

percentage =
    (inputPercentage < 0 || inputPercentage > 100) ?
    0 :
    inputPercentage;

Isn't there a smarter way to do such things within .NET Framework?

I know I can write a general method int LimitToRange(int value, int inclusiveMinimum, int inlusiveMaximum) and use it in every project, but maybe there is already a magic method in the framework?

If I need to do it manually, what would be the "best" (ie. less uglier and more fast) way to do what I'm doing in the first example? Something like this?

public i开发者_开发知识库nt LimitToRange(int value, int inclusiveMinimum, int inlusiveMaximum)
{
    if (value >= inclusiveMinimum)
    {
        if (value <= inlusiveMaximum)
        {
            return value;
        }

        return inlusiveMaximum;
    }

    return inclusiveMinimum;
}


This operation is called 'Clamp' and it's usually written like this:

public static int Clamp( int value, int min, int max )
{
    return (value < min) ? min : (value > max) ? max : value;
}


A much cleaner method that will work with more than just integers (taken from my own library of shared code):

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

    return value;
}


I see Mark's answer and raise it by a this:

public static class InputExtensions
{
    public static int LimitToRange(
        this int value, int inclusiveMinimum, int inclusiveMaximum)
    {
        if (value < inclusiveMinimum) { return inclusiveMinimum; }
        if (value > inclusiveMaximum) { return inclusiveMaximum; }
        return value;
    }
}

Usage:

int userInput = ...;

int result = userInput.LimitToRange(1, 5)

See: Extension Methods


I like Guffa's answer, but I am surprised that no one has yet posted a solution using Min/Max.

public int LimitInclusive(int value, int min, int max)
{
    return Math.Min(max, Math.Max(value, min));
}


An alternative way to write your LimitToRange function is as follows.

public int LimitToRange(int value, int inclusiveMinimum, int inclusiveMaximum)
{
    if (value < inclusiveMinimum) { return inclusiveMinimum; }
    if (value > inclusiveMaximum) { return inclusiveMaximum; }
    return value;
}

I think this is a little easier to understand while still being efficient.


No, there isn't any method for that built in the framework. I suppose that it was left out because you already have Min and Max, so you can accomplish it using them.

If you write your own method for it, it doesn't matter much how you write it. If you use if statements or the conditional operator ?, it will still compile to pretty much the same code anyway.


To clamp values without giving users any feedback that the value entered by them is wrong, in general, might not be a great idea (IMHO). This might lead to subtle bugs later, which are difficult to debug, especially when min/max values are determined at run time.

Think of this. You have $100 in your bank account, and you want to transfer $150 to your friend. Would you like your banking system to throw an InsufficientFundsException or get into a discussion with your friend that you transferred $150 but he received only $100 (assuming the bank clamped the transfer amount to 100 since your did not have sufficient funds)

That being said, you should also look at code contracts.

public void MyFunction (Type input)
{
   Contract.Requires(input > SomeReferenceValue);
   Contract.Requires (input < SomeOtherReferencValue);

}

This will force the user input to be within the range.


I like the Clamp name. I would suggest the following class

public class MathHelper
{
    public static int Clamp (int value,int min,int max)
    {
          // todo - implementation 
    }
    public static float Clamp (float value,float min,float max)
    {
          // todo - implementation 
    }
)

or if you want to use generics, then

public class MathHelper
{
     public static T Clamp<T> (T value, T min, T max) where T : IComparable
     {
         // todo - implementation
         T output = value;
         if (value.CompareTo(max) > 0)
         {
             return max;
         }
         if (value.CompareTo(min) < 0)
         {
            return min;
         }
        return  output;
     } 
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜