📜 ⬆️ ⬇️

Working with ranges and borders in .NET

From the translator. The topic of ranges (intervals) in .NET rightly refers to the ever-green and young. Hundreds of questions asked in the forums, dozens of written articles ... it seems that this will end only when Microsoft finally introduces its range management mechanism into the Framework Class Library. And there is a logical explanation for this - probably, every programmer sooner or later faces the need to use a certain range of values, be it numbers, dates, or any other values. I had such a need, however, remembering that my bikes are not the best solution, I went through the Internet and got into an excellent article by John Skit, a translation of which, in fact, I present to your attention.

The first edition of my book “ C # in Depth ” presented an abstract generalized class Range , in which virtual methods were used to walk through the elements in a range. Unfortunately, this class was not ideal, since it did not take into account certain borderline cases. However, this article is not so much about designing an ideal class for working with bands, but about what nuances and considerations should be taken into account. My MiscUtil class library contains a class that takes into account most of the things discussed in this article, but, of course, this class is far from ideal. In general, in January 2008, I wrote a short article about ranges in my blog, but since then a lot of water has flowed, I rethought a lot of things and decided to expand the topic in more detail in the form of this article.


Formulation of the problem


Let us first define what we want and what we can do, and formulate the problem as clearly as possible.

It seems that we seem to have described everything, but remember that the devil is in the details. We should also consider the following things, namely:

Now that we have formulated the problem in general terms, we can proceed to the fine details.
')

Details


First of all, let's think about the types that are generally acceptable for use in bands. We want the range class to be generic (generic), and we want to be able to compare (compare) two values ​​to each other, to know which one is larger and which one is smaller. We can achieve this by applying a delimiter to type T , which would require that type T implement the 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 .
interface 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 .
  1. 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 .
  2. 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 .
  3. 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 .
  4. 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 .

Source: https://habr.com/ru/post/197024/


All Articles