可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
This question already has an answer here:
-
Where can I find the “clamp” function in .NET?
7 answers
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 int LimitToRange(int value, int inclusiveMinimum, int inlusiveMaximum)
{
if (value >= inclusiveMinimum)
{
if (value <= inlusiveMaximum)
{
return value;
}
return inlusiveMaximum;
}
return inclusiveMinimum;
}
回答1:
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
回答2:
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;
}
回答3:
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;
}
回答4:
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.
回答5:
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));
}
回答6:
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.
回答7:
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.
回答8:
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;
}
}