O código a seguir suporta a especificação de limites em qualquer ordem (ou seja bound1 <= bound2
, ou bound2 <= bound1
). Eu achei isso útil para fixar valores calculados a partir de equações lineares (y=mx+b
), onde a inclinação da linha pode ser crescente ou decrescente.
Eu sei: o código consiste em cinco operadores de expressão condicional extremamente feios . A questão é que funciona e os testes abaixo provam isso. Sinta-se à vontade para adicionar parênteses estritamente desnecessários, se desejar.
Você pode criar facilmente outras sobrecargas para outros tipos numéricos e basicamente copiar / colar os testes.
Aviso: comparar números de ponto flutuante não é simples. Este código não implementa double
comparações de forma robusta. Use uma biblioteca de comparação de ponto flutuante para substituir os usos de operadores de comparação.
public static class MathExtensions
{
public static double Clamp(this double value, double bound1, double bound2)
{
return bound1 <= bound2 ? value <= bound1 ? bound1 : value >= bound2 ? bound2 : value : value <= bound2 ? bound2 : value >= bound1 ? bound1 : value;
}
}
Testes xUnit / FluentAssertions:
public class MathExtensionsTests
{
[Theory]
[InlineData(0, 0, 0, 0)]
[InlineData(0, 0, 2, 0)]
[InlineData(-1, 0, 2, 0)]
[InlineData(1, 0, 2, 1)]
[InlineData(2, 0, 2, 2)]
[InlineData(3, 0, 2, 2)]
[InlineData(0, 2, 0, 0)]
[InlineData(-1, 2, 0, 0)]
[InlineData(1, 2, 0, 1)]
[InlineData(2, 2, 0, 2)]
[InlineData(3, 2, 0, 2)]
public void MustClamp(double value, double bound1, double bound2, double expectedValue)
{
value.Clamp(bound1, bound2).Should().Be(expectedValue);
}
}