C#と.NET 3.5 / 4でこれをエレガントにするにはどうすればよいですか?
たとえば、1〜100の数値を指定できます。
私は単純なら十分だと思います。しかし、この質問のキーワードは優雅です。これは私のおもちゃプロジェクト用であり、制作用ではありません。
この質問は速度に関するものではなく、コードの美しさに関するものでした。効率などについて話すのをやめてください。あなたが合唱団に説教していることを思い出してください。
if
「バロック」でない場合は修正しないでください。
C#と.NET 3.5 / 4でこれをエレガントにするにはどうすればよいですか?
たとえば、1〜100の数値を指定できます。
私は単純なら十分だと思います。しかし、この質問のキーワードは優雅です。これは私のおもちゃプロジェクト用であり、制作用ではありません。
この質問は速度に関するものではなく、コードの美しさに関するものでした。効率などについて話すのをやめてください。あなたが合唱団に説教していることを思い出してください。
if
「バロック」でない場合は修正しないでください。
回答:
多くのオプションがあります:
int x = 30;
if (Enumerable.Range(1,100).Contains(x))
//true
if (x >= 1 && x <= 100)
//true
また、正規表現オプションについては、このSO投稿をご覧ください。
if
ステートメントよりも豪華なものを求めています。これは確かにそれを達成します...;)
もしかして?
if(number >= 1 && number <= 100)
または
bool TestRange (int numberToCheck, int bottom, int top)
{
return (numberToCheck >= bottom && numberToCheck <= top);
}
ここでノイズを追加するために、拡張メソッドを作成できます。
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);
そうは言っても、チェック自体が1行だけの場合、これは愚かなことのように思えます。
他の人が言ったように、単純なifを使用します。
順序について考える必要があります。
例えば
1 <= x && x <= 100
より読みやすいです
x >= 1 && x <= 100
=
代わりに入力したときにコンパイラーから通知されます==
。等しくない関係演算子には役立ちませんが、一貫して使用することに慣れるのは簡単です。
x
複雑な関数呼び出しまたは時間のかかるLinq式を検討してください。この場合、これを2回実行するのは良いことではありません。確かに一時的なローカル変数に値を格納する必要がありますが、他のifまたはelse-ifが失敗した後にのみ関数を呼び出したい場合があります(else-ifステートメントなど)。一時変数では、とにかくそれらを呼び出す必要があります。(他の回答で言及されている)拡張メソッドは、それらの場合に最適なソリューションです。
量産コードでは単純に次のように書きます
1 <= x && x <= 100
これは理解しやすく、非常に読みやすいです。
これは、いくつかの数学を使用して比較の数を2から1に減らす賢い方法です。アイデアは、数値が範囲外にある場合は2つの要素のいずれかが負になり、数値が境界の1つに等しい場合はゼロになるということです。
境界が包括的である場合:
(x - 1) * (100 - x) >= 0
または
(x - min) * (max - x) >= 0
境界が排他的である場合:
(x - 1) * (100 - x) > 0
または
(x - min) * (max - x) > 0
1 < x && x < 100
生産的なコードを使用します。理解しやすいです。
1 < x & x < 100
(&&短絡なし)は、コンパイラーにx < 100
、の結果に関係なく常に評価できるように指示し1 < x
ます。奇妙なことに(分岐予測のため)この単純な操作は、スキップするよりも常に高速です。
私はこれを提案します:
public static bool IsWithin<T>(this T value, T minimum, T maximum) where T : IComparable<T> {
if (value.CompareTo(minimum) < 0)
return false;
if (value.CompareTo(maximum) > 0)
return false;
return true;
}
例:
45.IsWithin(32, 89)
true
87.2.IsWithin(87.1, 87.15)
false
87.2.IsWithin(87.1, 87.25)
true
そしてもちろん変数を使って:
myvalue.IsWithin(min, max)
読みやすく(人間の言語に近い)、同等のタイプ(整数、ダブル、カスタムタイプなど)で動作します。
開発者はコードを理解するために「頭脳サイクル」を無駄にしないため、コードを読みやすくすることは重要です。長時間のコーディングセッションでは、脳のサイクルが無駄になるため、開発者は以前に疲れてバグになりやすくなります。
IsInRange. I'm not that keen on Ben's inclusive boolean as that requires a few more brain cycles. It has the advantage that it can be used in any class that that implements IComparer. This is in my Extensions now along with
LiesWithin / LiesInside. Just can't decide which.
NotOutside の名前を変更しましたが、うまくいきませんが、マイナスの条件は好きではありません
拡張メソッドを少し悪用すると、次の「エレガントな」ソリューションが得られます。
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!");
}
}
}
enum Inclusive
:値を使用してLower
、Upper
、All
。そして、のために渡すIn
機能タイプの1つの追加パラメータenum Inclusive
のデフォルト値とをInclusive.All
更新し、To
ハンドルに関数本体をAll
、Lower
、Upper
値:)
これが付随的であるif
場合、必要なのは単純なものだけです。これが多くの場所で発生する場合は、次の2つを検討することをお勧めします。
何かのようなもの:
[Between("parameter", 0, 100)]
public void Foo(int parameter)
{
}
&&
式を使用して2つの比較を結合することは、これを行う最もエレガントな方法です。派手な拡張メソッドなどを使用しようとすると、上限、下限、またはその両方を含めるかどうかという疑問にぶつかります。追加の変数を追加したり、何が含まれているかを示すために拡張名を変更したりすると、コードが長くなり、読みにくくなります(大多数のプログラマにとって)。さらに、比較が意味をなさない場合、Resharperなどのツールによって警告が表示されます(number > 100 && number < 1
)、メソッド( 'i.IsBetween(100、1)')を使用する。
私が行う他の唯一のコメントは、例外をスローする意図で入力をチェックしている場合は、コードコントラクトの使用を検討する必要があるということです。
Contract.Requires(number > 1 && number < 100)
これはよりエレガントでif(...) throw new Exception(...)
、最初に数値が境界内にあることを確認せずに誰かがメソッドを呼び出そうとすると、コンパイル時の警告が表示されることさえあります。
単純なifよりも多くのコードを記述したい場合は、次の方法が考えられます。IsBetweenという拡張メソッドを作成する
public static class NumberExtensionMethods
{
public static bool IsBetween(this long value, long Min, long Max)
{
// return (value >= Min && value <= Max);
if (value >= Min && value <= Max) return true;
else return false;
}
}
...
// Checks if this number is between 1 and 100.
long MyNumber = 99;
MessageBox.Show(MyNumber.IsBetween(1, 100).ToString());
補遺:実際には、コードベースで「等しいかどうかを確認するだけ」(または<、>)を行うことはほとんどありません。(最も些細な状況を除いて)純粋に例として、すべてのゲームプログラマーは基本的に、すべてのプロジェクトで次のようなカテゴリを使用します。この例では、その環境に組み込まれている関数(Mathf.Approximately)を使用していることに注意してください。実際には、通常、エンジニアリングしている状況のタイプに応じて、実数のコンピューター表現の比較が何を意味するかについて、独自の概念を慎重に開発する必要があります。(おそらく、コントローラー、PIDコントローラーなどのようなことをしている場合、問題全体が中心になり、非常に困難になることは、プロジェクトの性質になることは述べないでください。
private bool FloatLessThan(float a, float b)
{
if ( Mathf.Approximately(a,b) ) return false;
if (a<b) return true;
return false;
}
private bool FloatLessThanZero(float a)
{
if ( Mathf.Approximately(a,0f) ) return false;
if (a<0f) return true;
return false;
}
private bool FloatLessThanOrEqualToZero(float a)
{
if ( Mathf.Approximately(a,0f) ) return true;
if (a<0f) return true;
return false;
}
return (value >= Min && value <= Max);
他のすべての答えは私によって発明されていないので、ここでは私の実装だけです:
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);
編集:新しい回答が提供されました。この質問への最初の回答を書いたとき、私はC#の使用を開始したばかりでしたが、後から考えると、私の「解決策」は素朴で非効率的であることがわかりました。
私の元の答え:私はよりシンプルなバージョンを使います:
if(Enumerable.Range(1,100).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: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
実行時間:0.016秒
古いお気に入りの新しいひねり:
public bool IsWithinRange(int number, int topOfRange, int bottomOfRange, bool includeBoundaries) {
if (includeBoundaries)
return number <= topOfRange && number >= bottomOfRange;
return number < topOfRange && number > bottomOfRange;
}
Cでは、時間効率が重要であり、整数オーバーフローがラップする場合は、可能ですif ((unsigned)(value-min) <= (max-min)) ...
。「max」と「min」が独立変数である場合、(max-min)の追加の減算は時間を浪費しますが、その式がコンパイル時に事前計算できる場合、または実行時に一度計算して多くをテストできる場合同じ範囲に対する数値は、上記の式は、値の大部分が有効範囲未満になる場合、それはより速く使用することもできる(偶数値が範囲内にある場合に、効率的に計算することができるif ((value >= min) && (value <= max)) ...
、それがするので早期終了値場合は分未満です)。
ただし、このような実装を使用する前に、ターゲットマシンのベンチマークを行ってください。一部のプロセッサでは、2つの比較は独立して実行できるため、2つの部分からなる式の方が高速な場合があります。一方、減算と比較の方法では、比較を実行する前に減算を完了する必要があります。
このようなものはどうですか?
if (theNumber.isBetween(low, high, IntEx.Bounds.INCLUSIVE_INCLUSIVE))
{
}
次の拡張メソッドを使用します(テスト済み):
public static class IntEx
{
public enum Bounds
{
INCLUSIVE_INCLUSIVE,
INCLUSIVE_EXCLUSIVE,
EXCLUSIVE_INCLUSIVE,
EXCLUSIVE_EXCLUSIVE
}
public static bool isBetween(this int theNumber, int low, int high, Bounds boundDef)
{
bool result;
switch (boundDef)
{
case Bounds.INCLUSIVE_INCLUSIVE:
result = ((low <= theNumber) && (theNumber <= high));
break;
case Bounds.INCLUSIVE_EXCLUSIVE:
result = ((low <= theNumber) && (theNumber < high));
break;
case Bounds.EXCLUSIVE_INCLUSIVE:
result = ((low < theNumber) && (theNumber <= high));
break;
case Bounds.EXCLUSIVE_EXCLUSIVE:
result = ((low < theNumber) && (theNumber < high));
break;
default:
throw new System.ArgumentException("Invalid boundary definition argument");
}
return result;
}
}
Rangeオブジェクトを次のように実行します。
public class Range<T> where T : IComparable
{
public T InferiorBoundary{get;private set;}
public T SuperiorBoundary{get;private set;}
public Range(T inferiorBoundary, T superiorBoundary)
{
InferiorBoundary = inferiorBoundary;
SuperiorBoundary = superiorBoundary;
}
public bool IsWithinBoundaries(T value){
return InferiorBoundary.CompareTo(value) > 0 && SuperiorBoundary.CompareTo(value) < 0;
}
}
次に、次のように使用します。
Range<int> myRange = new Range<int>(1,999);
bool isWithinRange = myRange.IsWithinBoundaries(3);
そうすれば、別のタイプに再利用できます。
Range
オブジェクトが使用する必要がCompareTo
ない、アイテムを比較するための方法を<
オペレータ。
IComparable
し、<
オペレーターをオーバーロードしないことは完全に合理的です。
「数値」が範囲内にあるかどうかを確認するとき、あなたはあなたが何を意味するのかを明確にする必要があります、そして2つの数値が等しいとはどういう意味ですか?一般に、すべての浮動小数点数を「イプシロンボール」と呼ばれるものにラップする必要があります。これは、いくつかの小さな値を選択し、2つの値がこれに近いかどうかを示すことで行われます。
private double _epsilon = 10E-9;
/// <summary>
/// Checks if the distance between two doubles is within an epsilon.
/// In general this should be used for determining equality between doubles.
/// </summary>
/// <param name="x0">The orgin of intrest</param>
/// <param name="x"> The point of intrest</param>
/// <param name="epsilon">The minimum distance between the points</param>
/// <returns>Returns true iff x in (x0-epsilon, x0+epsilon)</returns>
public static bool IsInNeghborhood(double x0, double x, double epsilon) => Abs(x0 - x) < epsilon;
public static bool AreEqual(double v0, double v1) => IsInNeghborhood(v0, v1, _epsilon);
これらの2つのヘルパーを配置し、必要な精度なしに任意の数をdoubleとしてキャストできると仮定します。今必要なのは列挙型と別のメソッドだけです
public enum BoundType
{
Open,
Closed,
OpenClosed,
ClosedOpen
}
他の方法は次のとおりです。
public static bool InRange(double value, double upperBound, double lowerBound, BoundType bound = BoundType.Open)
{
bool inside = value < upperBound && value > lowerBound;
switch (bound)
{
case BoundType.Open:
return inside;
case BoundType.Closed:
return inside || AreEqual(value, upperBound) || AreEqual(value, lowerBound);
case BoundType.OpenClosed:
return inside || AreEqual(value, upperBound);
case BoundType.ClosedOpen:
return inside || AreEqual(value, lowerBound);
default:
throw new System.NotImplementedException("You forgot to do something");
}
}
これはあなたが望むものよりはるかに多いかもしれませんが、それはあなたがいつも丸めに対処し、値が丸められたかどうか、どこに丸められたかを覚えようとすることを防ぎます。必要に応じて、これを簡単に拡張して、任意のイプシロンで動作し、イプシロンを変更できるようにすることができます。
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);
受け入れられた回答に関する@Daapのコメントに懸念があり、値を一度しか渡せない場合は、次のいずれかを試すことができます
bool TestRangeDistance (int numberToCheck, int bottom, int distance)
{
return (numberToCheck >= bottom && numberToCheck <= bottom+distance);
}
//var t = TestRangeDistance(10, somelist.Count()-5, 10);
または
bool TestRangeMargin (int numberToCheck, int target, int margin)
{
return (numberToCheck >= target-margin && numberToCheck <= target+margin);
}
//var t = TestRangeMargin(10, somelist.Count(), 5);
エレガンスに関して、数学的表記に最も近いもの(a <= x <= b)は、読みやすさをわずかに向上させます。
public static bool IsBetween(this int value, int min, int max)
{
return min <= value && value <= max;
}
詳細な説明:
public static bool IsOutside(this int value, int min, int max)
{
return value < min || max < value;
}
私は境界が切り替わる可能性がある場所でそれを行うためのエレガントな方法を探していました(つまり、値の順序がわからない)。
これは、?:が存在する新しいバージョンのC#でのみ機能します
bool ValueWithinBounds(float val, float bounds1, float bounds2)
{
return bounds1 >= bounds2 ?
val <= bounds1 && val >= bounds2 :
val <= bounds2 && val >= bounds1;
}
もちろん、目的のために=記号を変更することもできます。型キャストも気に入るかもしれません。範囲内(または等しい)の浮動小数点数の戻り値が必要でした
2つの境界値のどちらが最初に大きいかを判別する必要がないため、エレガントです。また、ブランチも含まれていません。
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);
}
これらは助けることができるいくつかの拡張メソッドです
public static bool IsInRange<T>(this T value, T min, T max)
where T : System.IComparable<T>
{
return value.IsGreaterThenOrEqualTo(min) && value.IsLessThenOrEqualTo(max);
}
public static bool IsLessThenOrEqualTo<T>(this T value, T other)
where T : System.IComparable<T>
{
var result = value.CompareTo(other);
return result == -1 || result == 0;
}
public static bool IsGreaterThenOrEqualTo<T>(this T value, T other)
where T : System.IComparable<T>
{
var result = value.CompareTo(other);
return result == 1 || result == 0;
}
メソッドのパラメーターを検証する場合、どのソリューションもArgumentOutOfRangeExceptionをスローせず、包括的/排他的最小/最大値の簡単/適切な設定を可能にします。
このように使う
public void Start(int pos)
{
pos.CheckRange(nameof(pos), min: 0);
if (pos.IsInRange(max: 100, maxInclusive: false))
{
// ...
}
}
私はこれらの美しい関数を書いただけです。また、有効な値に分岐がない(ifが1つ)という利点もあります。最も難しいのは、適切な例外メッセージを作成することです。
/// <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 [1..100]
ですか?それはパスカルだけです。
when (number) { in 0..9 -> println("1 digit") in 10..99 -> println("2 digits") in 100..999 -> println("3 digits") }