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

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

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

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


当前回答

static class ExtensionMethods
{
    internal static bool IsBetween(this double number,double bound1, double bound2)
    {
        return Math.Min(bound1, bound2) <= number && number <= Math.Max(bound2, bound1);
    }

    internal static bool IsBetween(this int number, double bound1, double bound2)
    {
        return Math.Min(bound1, bound2) <= number && number <= Math.Max(bound2, bound1);
    }
}

使用

double numberToBeChecked = 7;

var result = numberToBeChecked.IsBetween(100,122);

var result = 5.IsBetween(100,120);

var result = 8.0.IsBetween(1.2,9.6);

其他回答

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

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

}

编辑:提供了新的答案。 当我写这个问题的第一个答案时,我刚刚开始使用c#,事后我意识到我的“解决方案”是幼稚和低效的。

我最初的回答是: 我会选择更简单的版本:

' if(Enumerable.Range(1100).Contains(intInQuestion)){…DoStuff;} '

更好的方法

因为我还没有看到任何其他更有效的解决方案(至少根据我的测试),我将再试一次。

新的和更好的方法,也适用于负范围:

// Returns true if x is in range [min..max], else false 
bool inRange(int x, int min=1, int max=100) => ((x - max)*(x - min) <= 0);

这可以用于正负范围,并且默认为

1 . . 100(包括)并使用x作为数字来检查,然后是由min和max定义的可选范围。

为好的措施添加例子

示例1:

// Returns true if x is in range [min..max], else false 
bool inRange(int x, int min=1, int max=100) => ((x - max)*(x - min) <= 0);

Console.WriteLine(inRange(25));
Console.WriteLine(inRange(1));
Console.WriteLine(inRange(100));
Console.WriteLine(inRange(25, 30, 150));
Console.WriteLine(inRange(-25, -50, 0));

返回:

True
True
True
False
True

示例2: 使用100000个1到150之间的随机整数的列表

// Returns true if x is in range [min..max], else false 
bool inRange(int x, int min=1, int max=100) => ((x - max)*(x - min) <= 0);

// Generate 100000 ints between 1 and 150
var intsToCheck = new List<int>();
var randGen = new Random();
for(int i = 0; i < 100000; ++i){
    intsToCheck.Add(randGen.Next(150) + 1);
}

var counter = 0;
foreach(int n in intsToCheck) {
    if(inRange(n)) ++counter;
}

Console.WriteLine("{0} ints found in range 1..100", counter);

返回:

66660 ints found in range 1..100

Execution Time: 0.016 second(s)

Using an && expression to join two comparisons is simply the most elegant way to do this. If you try using fancy extension methods and such, you run into the question of whether to include the upper bound, the lower bound, or both. Once you start adding additional variables or changing the extension names to indicate what is included, your code becomes longer and harder to read (for the vast majority of programmers). Furthermore, tools like Resharper will warn you if your comparison doesn't make sense (number > 100 && number < 1), which they won't do if you use a method ('i.IsBetween(100, 1)').

我要做的唯一另一个评论是,如果你检查输入的意图是抛出异常,你应该考虑使用代码契约:

Contract.Requires(number > 1 && number < 100)

这比if(…)抛出new Exception(…)更优雅,如果有人试图调用您的方法而没有首先确保该数字在边界内,您甚至可以得到编译时警告。

我使用下一个“优雅”的解决方案:

using static System.Linq.Enumerable;

int x = 30;
if (Range(1,100).Contains(x))  //true

来自微软文档

using static指令适用于任何具有静态成员(或嵌套类型)的类型,即使它也具有实例成员。但是,实例成员只能通过类型实例调用。

你可以访问一个类型的静态成员,而不需要用类型名限定访问:

但这对许多人来说并不简单,因为Enumerable。Range有第一个参数start和第二个参数count。 所以这种检查可能在特定情况下有用,比如当你使用Enumerable时。范围的foreach循环,在开始之前,您想知道,如果循环将执行。

例如:

        int count = 100;
        int x = 30;

        if (!Range(1, count).Contains(x)) {
            Console.WriteLine("Do nothing!");
            return;
        }

        foreach (var i in Range(1, count)) {
            // Some job here
        }

只是为了增加这里的噪音,你可以创建一个扩展方法:

public static bool IsWithin(this int value, int minimum, int maximum)
{
    return value >= minimum && value <= maximum;
}

这样你就能做…

int val = 15;

bool foo = val.IsWithin(5,20);

话虽如此,当检查本身只有一行时,这样做似乎是一件愚蠢的事情。