c# - visual - variables vb net
¿Cómo forzar a un número a estar en un rango en C#? (8)
Esta pregunta ya tiene una respuesta aquí:
En C #, a menudo tengo que limitar un valor entero a un rango de valores. Por ejemplo, si una aplicación espera un porcentaje, un número entero de una entrada de usuario no debe ser menor que cero o más de cien. Otro ejemplo: si hay cinco páginas web a las que se accede a través de Request.Params["p"]
, espero un valor de 1 a 5, no 0 o 256 o 99999.
A menudo termino escribiendo un código bastante feo como:
page = Math.Max(0, Math.Min(2, page));
o incluso más feo:
percentage =
(inputPercentage < 0 || inputPercentage > 100) ?
0 :
inputPercentage;
¿No hay una forma más inteligente de hacer tales cosas dentro de .NET Framework?
Sé que puedo escribir un método general int LimitToRange(int value, int inclusiveMinimum, int inlusiveMaximum)
y usarlo en cada proyecto, pero ¿quizás ya hay un método mágico en el framework?
Si tengo que hacerlo manualmente, ¿cuál sería la "mejor" (es decir, menos fea y más rápida) manera de hacer lo que estoy haciendo en el primer ejemplo? ¿Algo como esto?
public int LimitToRange(int value, int inclusiveMinimum, int inlusiveMaximum)
{
if (value >= inclusiveMinimum)
{
if (value <= inlusiveMaximum)
{
return value;
}
return inlusiveMaximum;
}
return inclusiveMinimum;
}
Esta operación se llama ''Clamp'' y generalmente se escribe así:
public static int Clamp( int value, int min, int max )
{
return (value < min) ? min : (value > max) ? max : value;
}
Me gusta el nombre de Clamp. Sugeriría la siguiente clase
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
}
)
o si quieres usar genéricos, entonces
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;
}
}
Me gusta la respuesta de Guffa, pero me sorprende que nadie haya publicado una solución usando Min / Max.
public int LimitInclusive(int value, int min, int max)
{
return Math.Min(max, Math.Max(value, min));
}
No, no hay ningún método para eso construido en el marco. Supongo que se dejó de lado porque ya tienes Min
y Max
, así que puedes lograrlo usándolos.
Si escribes tu propio método para ello, no importa mucho cómo lo escribes. Si usa if
declaraciones o el operador condicional ?
, de todos modos se compilará prácticamente con el mismo código.
Para fijar valores sin dar a los usuarios ningún comentario de que el valor ingresado por ellos es incorrecto, en general, podría no ser una gran idea (en mi humilde opinión). Esto podría conducir a errores sutiles más adelante, que son difíciles de depurar, especialmente cuando los valores mínimos / máximos se determinan en tiempo de ejecución.
Piense en esto. Tiene $ 100 en su cuenta bancaria y desea transferir $ 150 a su amigo. ¿Le gustaría que su sistema bancario arroje una InsufficientFundsException
o InsufficientFundsException
una discusión con su amigo acerca de que transfirió $ 150 pero recibió solo $ 100 (suponiendo que el banco bloqueó el monto de la transferencia a 100 debido a que no tenía suficientes fondos)?
Dicho esto, también debe mirar los contratos de código.
public void MyFunction (Type input)
{
Contract.Requires(input > SomeReferenceValue);
Contract.Requires (input < SomeOtherReferencValue);
}
Esto obligará a la entrada del usuario a estar dentro del rango.
Un método mucho más limpio que funcionará con algo más que enteros (tomado de mi propia biblioteca de código compartido):
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;
}
Una forma alternativa de escribir su función LimitToRange
es la siguiente.
public int LimitToRange(int value, int inclusiveMinimum, int inclusiveMaximum)
{
if (value < inclusiveMinimum) { return inclusiveMinimum; }
if (value > inclusiveMaximum) { return inclusiveMaximum; }
return value;
}
Creo que esto es un poco más fácil de entender sin dejar de ser eficiente.
Veo la respuesta de Marcos y lo planteo de la siguiente manera:
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;
}
}
Uso:
int userInput = ...;
int result = userInput.LimitToRange(1, 5)
Ver: Métodos de extensión