私の本の初版「 C#in Depth 」は、仮想メソッドを使用して範囲内の要素をトラバースする抽象的な汎用
Range
クラスを引用しました。 残念ながら、このクラスは特定の境界線のケースを考慮していないため、不完全でした。 ただし、この記事では、範囲を操作するための理想的なクラスの設計についてではなく、どのニュアンスと考慮事項を考慮する必要があるかについて説明します。 私のMiscUtilクラスライブラリには、この記事で説明したほとんどのことを考慮したクラスが含まれていますが、もちろん、このクラスは理想からはほど遠いものです。 一般的に、2008年1月にブログで範囲に関する短い記事を書きましたが、それ以来多くの水が流れ、多くのことを再考し、この記事の形でトピックをより詳細に展開することにしました。
問題の声明
まず、私たちが何をしたいのか、何ができるのかを決めましょう。できるだけ一意にタスクを定式化します。
- 適切なタイプの値範囲ストレージエンジンを作成する
- カスタム列挙関数を使用して、これらの値のセットを反復処理します
私たちはすべてを説明しているように見えますが、悪魔は細部に宿っていることを忘れないでください。 また、次のことも考慮する必要があります。
- 2つの範囲が等しいことを考慮してください
- 交差点、結合、差異などを考慮してください。 2つの範囲
- 値が離散値である範囲を考慮します(「0〜100の範囲のすべての偶数整数」など)
- 範囲内で「移動」する必要がある検索機能を処理する(つまり、移動する方向を決定するなど)
一般的な用語で問題を定式化したので、細かい部分に進むことができます。
詳細
まず、範囲での使用に一般的に有効なタイプについて考えてみましょう。 範囲クラスをジェネリックにし、どちらが大きいか、小さいかを知るために、2つの値を互いに比較できるようにします。 このような制約をタイプ
T
に適用することでこれを達成できますが、タイプ
T
は
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null «» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
インターフェイスを実装する必要があります
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null «» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
-
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null «» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
-
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null «» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
-
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null «» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
-
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null «» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
-
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
-
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
-
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , - null
; « », null
— , . , , , default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , . Contains
, - , .
() (). , , . ( readonly
) - , .
WithExclusiveLowerBound
, WithInclusiveLowerBound
, WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , - IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: , IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255) Byte
. :
: , , — . , «». :
* Func<Tuple<bool, T>>
, .
* ( out
) ( )
* null
« », , T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? , Compare
(negate) … , originalComparer.Compare
int.MinValue
. , , int.MinValue
. — , , , .
. , int.MinValue
. IComparer , , , int Compare(T x, T y) , : x
y
0; x
y
, 0; x
, y
, 0. .NET Framework, , x
y
-1 +1, , int.MinValue
( x
y
) int.MaxValue
( x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
, int.MaxValue
, . , ( checked
), System.OverflowException
, production- .
, , Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . , [0, 5]
(.. 0 5 ), , 2 . { 0, 2, 4 }
. [0, 5]
[5, 0]
, ( , 2), { 5, 3, 1 }
. , , LINQ, { 4, 2, 0 }
— { 5, 3, 1 }
.
, « », , . , ; , , . , , , , int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , , RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,
default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -
IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,
IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .
IComparable. , , C# — IComparable. , , . , , (reversing) , . , .
— , «-», , (). : IComparer, Comparison? , IComparer, , , . , Comparer.Default . , , Comparison, , - ( MiscUtil).
, , : «» , , , , «» ? , , , «», API .
, , , , . :
() (inclusive) (exclusive), , . , , ? , , .. ? , ()? , ?
, , .. , , . , (), — (). , , «» «» . , , . null
«» , -null
; « »,null
— , . , , ,default(IComparer), , , null
. .
, : (immutable). , , , , , «» (, ) .
. — .
public sealed class Range<T> { public T LowerBound { get; private set; } public T UpperBound { get; private set; } public bool InclusiveLowerBound { get; private set; } public bool InclusiveUpperBound { get; private set; } public IComparer<T> Comparer { get; private set; } public Range(T lowerBound, T upperBound, bool inclusiveLowerBound = true, bool inclusiveUpperBound = false, IComparer<T> comparer = null) { LowerBound = lowerBound; UpperBound = upperBound; InclusiveLowerBound = inclusiveLowerBound; InclusiveUpperBound = inclusiveUpperBound; Comparer = comparer ?? Comparer<T>.Default; if (Comparer.Compare(LowerBound, UpperBound) > 0) { throw new ArgumentException("Invalid bounds"); } } public bool Contains(T item) { int lowerCompare = Comparer.Compare(LowerBound, item); if (lowerCompare > (InclusiveLowerBound ? 0 : -1)) { return false; } int upperCompare = Comparer.Compare(item, UpperBound); if (upperCompare > (InclusiveUpperBound ? 0 : -1)) { return false; } return true; } }
, , , … . , «» (.. ) / , .Contains
, - , .
() (). , , . (readonly
) - , .
WithExclusiveLowerBound
,WithInclusiveLowerBound
,WithLowerBound
.., . -, , . - :
var range = Range.Of(5, 10);
, — ́ , , . , , .
. , ( , stepping function), . : , , .
?
, — . , — . , (0, 50), , — 5. 1 ( ) 5 ( 0 )? , , , () . , -IComparer, . «» (41, 37), 23, 12 44, 38. .
, , . , — , , :
var range = new Range<int>(0, 50, false, false); var simpleIterable = range.StepBy(x => x + 5); var equivalentIterable = range.WithInclusiveLowerBound() .StepBy(x => x + 5) .Skip(1);
: ,IEnumerable. IEnumerator, IEnumerable: foreach
, LINQ ..
, …
?
-, . , «» , , . , , (0, 255)Byte
. :
: , , — . , «». :
*Func<Tuple<bool, T>>
, .
* (out
) ( )
*null
« », ,T
.
, «» - , () ( «»).
, , , , , « n ». , , , .
, , , . MiscUtil, , — . , . MiscUtil ( Marc Gravell ), , (+), , .
, :
public IEnumerable<T> StepBy(Func<T, T> step) { T current = LowerBound; // , if (!InclusiveLowerBound) { current = step(current); } while (Contains(current)) { yield return current; T next = step(current); // Handle a stepping function which wraps // round from a value near the end to one // near the start; or a stepping function // which does nothing. if (Comparer.Compare(next, current) <= 0) { yield break; } current = next; } }
: «» , , , . , : , , , , , , , .
( if) — :
T current = InclusiveLowerBound ? LowerBound : step(LowerBound);
— , — .
: . , — ?
(reversing) , . , «» / «» , . , (reversing comparer) — , , . , «» :
public sealed class ReverseComparer<T> : IComparer<T> { private readonly IComparer<T> originalComparer; public ReverseComparer(IComparer<T> originalComparer) { this.originalComparer = originalComparer; } public int Compare(T x, T y) { return originalComparer.Compare(y, x); } }
« », ? ,Compare
(negate) … ,originalComparer.Compare
int.MinValue
. , ,int.MinValue
. — , , , .
. ,int.MinValue
.
IComparer , , , int Compare(T x, T y) , : x
y
0;x
y
, 0;x
,y
, 0. .NET Framework, ,x
y
-1 +1, ,int.MinValue
(x
y
)int.MaxValue
(x
y
). , . 0 ,
|int.MinValue| == int.MaxValue + 1. ,
Int32 i = Int32.MinValue; Int32 j = -i;
j
int.MinValue
,int.MaxValue
, . , (checked
),System.OverflowException
, production- .
, ,Range
Reverse
:
public Range<T> Reverse() { return new Range<T>( lowerBound: UpperBound, upperBound: LowerBound, inclusiveLowerBound: InclusiveUpperBound, inclusiveUpperBound: InclusiveLowerBound, comparer:new ReverseComparer<T>(Comparer)); }
, , , «» ( , ), . , C# 4, , , , .
, : , , , . ,[0, 5]
(.. 0 5 ), , 2 .{ 0, 2, 4 }
.[0, 5]
[5, 0]
, ( , 2),{ 5, 3, 1 }
. , , LINQ,{ 4, 2, 0 }
—{ 5, 3, 1 }
.
, « », , . , ; , , . , , , ,int.MinValue
. , , -, .
, , , .NET.
Dmitri Nstruk. Ranges in C# Qwertie. D-style ranges in C# (.NET) Sean Hederman. Building a Generic Range class Scott McMaster. RangeSet: A Low-Memory Set Data Structure for Integers Jay Bazuzi. Comparing ranges Sergio Pereira. Language Envy - C# needs Ranges Andy Clymer. Ruby Ranges in .NET
, , MiscUtil. , , . -, , , . Range MiscUtil , ,RangeIterator. , MiscUtil, , " ".
, Time Period Library Jani Giannoudis. 2011 CodeProject, ( — 1 2013), - ( - ), Silverlight Windows Phone. overkill hDrummer .