我如何用c#优雅地做到这一点?

例如,一个数字可以是1到100之间。

我知道一个简单的if (x >= 1 && x <= 100)就足够了;但是有很多语法糖和新特性不断添加到c# /。Net这个问题是关于更习惯的(一个可以称之为优雅的)写法。

性能不是问题,但请在非O(1)的解决方案中添加性能说明,因为人们可能会复制粘贴建议。


当前回答

您可以使用模式匹配以最优雅的方式实现这一点:

int i = 5;
if(i is (>0 and <=10))
{

}

其他回答

我不知道,但我用这个方法:

    public static Boolean isInRange(this Decimal dec, Decimal min, Decimal max, bool includesMin = true, bool includesMax = true ) {

    return (includesMin ? (dec >= min) : (dec > min)) && (includesMax ? (dec <= max) : (dec < max));
}

这是我使用它的方式:

    [TestMethod]
    public void IsIntoTheRange()
    {
        decimal dec = 54;

        Boolean result = false;

        result = dec.isInRange(50, 60); //result = True
        Assert.IsTrue(result);

        result = dec.isInRange(55, 60); //result = False
        Assert.IsFalse(result);

        result = dec.isInRange(54, 60); //result = True
        Assert.IsTrue(result);

        result = dec.isInRange(54, 60, false); //result = False
        Assert.IsFalse(result);

        result = dec.isInRange(32, 54, false, false);//result = False
        Assert.IsFalse(result);

        result = dec.isInRange(32, 54, false);//result = True
        Assert.IsTrue(result);
    }

新花样的老最爱:

public bool IsWithinRange(int number, int topOfRange, int bottomOfRange, bool includeBoundaries) {
    if (includeBoundaries)
        return number <= topOfRange && number >= bottomOfRange;
    return number < topOfRange && number > bottomOfRange;
}

如果是为了验证方法参数,没有一个解决方案会抛出argumentoutofranceexception,并允许简单/适当地配置包含/排除的最小/最大值。

像这样使用

public void Start(int pos)
{
    pos.CheckRange(nameof(pos), min: 0);

    if (pos.IsInRange(max: 100, maxInclusive: false))
    {
        // ...
    }
}

我只是写出了这些漂亮的函数。它还具有对有效值没有分支(单个if)的优点。最难的部分是制作适当的异常消息。

/// <summary>
/// Returns whether specified value is in valid range.
/// </summary>
/// <typeparam name="T">The type of data to validate.</typeparam>
/// <param name="value">The value to validate.</param>
/// <param name="min">The minimum valid value.</param>
/// <param name="minInclusive">Whether the minimum value is valid.</param>
/// <param name="max">The maximum valid value.</param>
/// <param name="maxInclusive">Whether the maximum value is valid.</param>
/// <returns>Whether the value is within range.</returns>
public static bool IsInRange<T>(this T value, T? min = null, bool minInclusive = true, T? max = null, bool maxInclusive = true)
    where T : struct, IComparable<T>
{
    var minValid = min == null || (minInclusive && value.CompareTo(min.Value) >= 0) || (!minInclusive && value.CompareTo(min.Value) > 0);
    var maxValid = max == null || (maxInclusive && value.CompareTo(max.Value) <= 0) || (!maxInclusive && value.CompareTo(max.Value) < 0);
    return minValid && maxValid;
}

/// <summary>
/// Validates whether specified value is in valid range, and throws an exception if out of range.
/// </summary>
/// <typeparam name="T">The type of data to validate.</typeparam>
/// <param name="value">The value to validate.</param>
/// <param name="name">The name of the parameter.</param>
/// <param name="min">The minimum valid value.</param>
/// <param name="minInclusive">Whether the minimum value is valid.</param>
/// <param name="max">The maximum valid value.</param>
/// <param name="maxInclusive">Whether the maximum value is valid.</param>
/// <returns>The value if valid.</returns>
public static T CheckRange<T>(this T value, string name, T? min = null, bool minInclusive = true, T? max = null, bool maxInclusive = true)
where T : struct, IComparable<T>
{
    if (!value.IsInRange(min, minInclusive, max, maxInclusive))
    {
        if (min.HasValue && minInclusive && max.HasValue && maxInclusive)
        {
            var message = "{0} must be between {1} and {2}.";
            throw new ArgumentOutOfRangeException(name, value, message.FormatInvariant(name, min, max));
        }
        else
        {
            var messageMin = min.HasValue ? GetOpText(true, minInclusive).FormatInvariant(min) : null;
            var messageMax = max.HasValue ? GetOpText(false, maxInclusive).FormatInvariant(max) : null;
            var message = (messageMin != null && messageMax != null) ?
                "{0} must be {1} and {2}." :
                "{0} must be {1}.";
            throw new ArgumentOutOfRangeException(name, value, message.FormatInvariant(name, messageMin ?? messageMax, messageMax));
        }
    }
    return value;
}

private static string GetOpText(bool greaterThan, bool inclusive)
{
    return (greaterThan && inclusive) ? "greater than or equal to {0}" :
        greaterThan ? "greater than {0}" :
        inclusive ? "less than or equal to {0}" :
        "less than {0}";
}

public static string FormatInvariant(this string format, params object?[] args) => string.Format(CultureInfo.InvariantCulture, format, args);

In production code I would simply write 1 <= x && x <= 100 This is easy to understand and very readable. Starting with C#9.0 we can write x is >= 1 and <= 100 Note that we must write x only once. is introduces a pattern matching expression where and is part of the pattern. && would require us to repeat x is as in x is >= 1 && x is <= 100 Here is a clever method that reduces the number of comparisons from two to one by using some math. There is not necessarily a performance advantage in doing so, but it is elegant. The idea is that one of the two factors becomes negative if the number lies outside of the range and zero if the number is equal to one of the bounds: If the bounds are inclusive: (x - 1) * (100 - x) >= 0 or (x - min) * (max - x) >= 0 If the bounds are exclusive: (x - 1) * (100 - x) > 0 or (x - min) * (max - x) > 0

就像其他人说的,使用简单的if。

你应该考虑一下顺序。

e.g

1 <= x && x <= 100

容易读吗

x >= 1 && x <= 100