如何强制数字在C#范围内?

时间:2010-07-04 23:47:23

标签: c# .net performance math

在C#中,我经常要将整数值限制为一系列值。例如,如果应用程序需要百分比,则用户输入中的整数不得小于零或大于一百。另一个例子:如果有五个网页可以通过Request.Params["p"]访问,我希望值为1到5,而不是0或256或99999。

我常常写一个非常难看的代码,如:

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

甚至更丑陋:

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

在.NET Framework中没有更聪明的方法来做这些事情吗?

我知道我可以编写一个通用方法int LimitToRange(int value, int inclusiveMinimum, int inlusiveMaximum)并在每个项目中使用它,但是框架中可能已经有一个神奇的方法了吗?

如果我需要手动完成,那么在第一个例子中做什么是“最好的”(即不那么丑陋和更快)的方式?像这样的东西?

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

        return inlusiveMaximum;
    }

    return inclusiveMinimum;
}

8 个答案:

答案 0 :(得分:53)

此操作称为“Clamp”,它通常写成:

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

答案 1 :(得分:26)

我看到马克的回答,并以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;
    }
}

用法:

int userInput = ...;

int result = userInput.LimitToRange(1, 5)

请参阅:Extension Methods

答案 2 :(得分:26)

一个更简洁的方法,不仅可以使用整数(取自我自己的共享代码库):

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;
}

答案 3 :(得分:7)

编写LimitToRange函数的另一种方法如下:

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

我认为这在保持高效的同时更容易理解。

答案 4 :(得分:7)

我喜欢Guffa的答案,但我很惊讶没有人使用Min / Max发布解决方案。

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

答案 5 :(得分:3)

不,没有任何方法可以在框架中构建。我认为它已被遗漏,因为您已经拥有MinMax,因此您可以使用它们来完成它。

如果您为自己编写自己的方法,那么编写它的方式并不重要。如果你使用if语句或条件运算符?,它仍然会编译成几乎相同的代码。

答案 6 :(得分:3)

为了限制值而不向用户提供任何反馈,即他们输入的值是错误的,一般来说,这可能不是一个好主意(恕我直言)。这可能会导致稍后的细微错误,这些错误很难调试,尤其是在运行时确定最小值/最大值时。

想一想。您的银行帐户中有100美元,而您希望将150美元转移给您的朋友。您是否希望您的银行系统抛出InsufficientFundsException或与您的朋友讨论您转移了150美元,但他只收到100美元(假设由于您没有足够的资金,银行将转账金额限制为100)< / p>

话虽如此,您还应该查看代码合同。

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

}

这将强制用户输入在范围内。

答案 7 :(得分:1)

我喜欢Clamp的名字。我会建议以下课程

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 
    }
)

或者如果你想使用泛型,那么

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;
     } 
}