我如何用c#优雅地做到这一点?
例如,一个数字可以是1到100之间。
我知道一个简单的if (x >= 1 && x <= 100)就足够了;但是有很多语法糖和新特性不断添加到c# /。Net这个问题是关于更习惯的(一个可以称之为优雅的)写法。
性能不是问题,但请在非O(1)的解决方案中添加性能说明,因为人们可能会复制粘贴建议。
我如何用c#优雅地做到这一点?
例如,一个数字可以是1到100之间。
我知道一个简单的if (x >= 1 && x <= 100)就足够了;但是有很多语法糖和新特性不断添加到c# /。Net这个问题是关于更习惯的(一个可以称之为优雅的)写法。
性能不是问题,但请在非O(1)的解决方案中添加性能说明,因为人们可能会复制粘贴建议。
当前回答
优雅是因为它不需要确定两个边界值中哪个先大。它也不包含分支。
public static bool InRange(float val, float a, float b)
{
// Determine if val lies between a and b without first asking which is larger (a or b)
return ( a <= val & val < b ) | ( b <= val & val < a );
}
其他回答
我不知道,但我用这个方法:
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);
}
使用内置的Range结构体(c# 8+),我们可以创建一个扩展方法来检查索引是否在原始范围内。
public static bool IsInRangeOf(this Range range, Index index)
{
return index.Value >= range.Start.Value && index.Value < range.End.Value;
}
由于Index覆盖隐式操作符,因此可以传递int型而不是Index结构体。
var range = new Range(1, 10);
var isInRange = range.IsInRangeOf(1); // true, 1..10 is inclusive min range index(1)
var isInRange = range.IsInRangeOf(10); // false, 1..10 exclusive on max range index (10).
var isInRange = range.IsInRangeOf(100); // false
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);
通过一些扩展方法的滥用,我们可以得到以下“优雅”的解决方案:
using System;
namespace Elegant {
public class Range {
public int Lower { get; set; }
public int Upper { get; set; }
}
public static class Ext {
public static Range To(this int lower, int upper) {
return new Range { Lower = lower, Upper = upper };
}
public static bool In(this int n, Range r) {
return n >= r.Lower && n <= r.Upper;
}
}
class Program {
static void Main() {
int x = 55;
if (x.In(1.To(100)))
Console.WriteLine("it's in range! elegantly!");
}
}
}
因为所有其他答案都不是我发明的,这里只是我的实现:
public enum Range
{
/// <summary>
/// A range that contains all values greater than start and less than end.
/// </summary>
Open,
/// <summary>
/// A range that contains all values greater than or equal to start and less than or equal to end.
/// </summary>
Closed,
/// <summary>
/// A range that contains all values greater than or equal to start and less than end.
/// </summary>
OpenClosed,
/// <summary>
/// A range that contains all values greater than start and less than or equal to end.
/// </summary>
ClosedOpen
}
public static class RangeExtensions
{
/// <summary>
/// Checks if a value is within a range that contains all values greater than start and less than or equal to end.
/// </summary>
/// <param name="value">The value that should be checked.</param>
/// <param name="start">The first value of the range to be checked.</param>
/// <param name="end">The last value of the range to be checked.</param>
/// <returns><c>True</c> if the value is greater than start and less than or equal to end, otherwise <c>false</c>.</returns>
public static bool IsWithin<T>(this T value, T start, T end) where T : IComparable<T>
{
return IsWithin(value, start, end, Range.ClosedOpen);
}
/// <summary>
/// Checks if a value is within the given range.
/// </summary>
/// <param name="value">The value that should be checked.</param>
/// <param name="start">The first value of the range to be checked.</param>
/// <param name="end">The last value of the range to be checked.</param>
/// <param name="range">The kind of range that should be checked. Depending on the given kind of range the start end end value are either inclusive or exclusive.</param>
/// <returns><c>True</c> if the value is within the given range, otherwise <c>false</c>.</returns>
public static bool IsWithin<T>(this T value, T start, T end, Range range) where T : IComparable<T>
{
if (value == null)
throw new ArgumentNullException(nameof(value));
if (start == null)
throw new ArgumentNullException(nameof(start));
if (end == null)
throw new ArgumentNullException(nameof(end));
switch (range)
{
case Range.Open:
return value.CompareTo(start) > 0
&& value.CompareTo(end) < 0;
case Range.Closed:
return value.CompareTo(start) >= 0
&& value.CompareTo(end) <= 0;
case Range.OpenClosed:
return value.CompareTo(start) > 0
&& value.CompareTo(end) <= 0;
case Range.ClosedOpen:
return value.CompareTo(start) >= 0
&& value.CompareTo(end) < 0;
default:
throw new ArgumentException($"Unknown parameter value {range}.", nameof(range));
}
}
}
然后你可以这样使用它:
var value = 5;
var start = 1;
var end = 10;
var result = value.IsWithin(start, end, Range.Closed);