Enhanced C#
Language of your choice: library documentation
|
A read-only list indexed by an integer. More...
A read-only list indexed by an integer.
Member list:
The term "source" means a read-only collection, as opposed to a "sink" which is a write-only collection. The purpose of IListSource is to support slices, eliminate the need to call Count
before reading from the list, and to make it easier to implement a read-only list, by lifting IList's requirement to write implementations for Add(), Remove(), etc. A secondary purpose is, of course, to guarantee users don't mistakenly call those methods on a read-only collection.
I have often wanted to access the "next" or "previous" item in a list, e.g. during parsing, but it inconvenient if you have to worry about whether the the current item is the first or last. In that case you must check whether the array index is valid, which is both inconvenient and wasteful, because the list class itself will check the array index a second time, and then the .NET runtime will check the index a third time when reading the internal array. The TryGet(index, defaultValue)
extension method can be used to return a default value if the index is not valid, using only one interface call.
Design footnote: I would have preferred to define TryGet
with one of these signatures:
However, these signatures don't allow T to be covariant (out T
). The first signature doesn't work because the .NET runtime doesn't distinguish between ref
and out
, so T could not be covariant. The second signature doesn't work if T
is not a value type. The third signature doesn't work because, as a struct, Maybe<T>
is not allowed to be covariant (even though the JIT could, theoretically, treat it covariantly).
Using Impl.ListSourceBase{T} as your base class can help you implement this interface more quickly.
Public Member Functions | |
T | TryGet (int index, out bool fail) |
Gets the item at the specified index, and does not throw an exception on failure. More... | |
IRange< T > | Slice (int start, int count=int.MaxValue) |
Returns a sub-range of this list. More... | |
IRange<T> Loyc.Collections.IListSource< out T >.Slice | ( | int | start, |
int | count = int.MaxValue |
||
) |
Returns a sub-range of this list.
start | The new range will start at this index in the current list (this location will be index [0] in the new range). |
count | The desired number of elements in the new range, or int.MaxValue to get all elements until the end of the list. |
ArgumentException | The start index was below zero. |
The (start, count) range is allowed to be invalid, as long as start is zero or above.
this.Count - start
. Implementation note: do not compute (start + count) because it may overflow. Instead, test whether (count > this.Count - start). Most collections should use the following implementation:
IRange<T> IListSource<T>.Slice(int start, int count) { return Slice(start, count); } public Slice_<T> Slice(int start, int count) { return new Slice_<T>(this, start, count); }
Implemented in Loyc.Collections.AListReverseView< K, T >, Loyc.Collections.AListReverseView< K, T >, Loyc.Collections.AListBase< K, T >, Loyc.Collections.AListBase< T >, Loyc.Collections.Impl.InternalDList< T >, Loyc.Collections.Impl.InternalDList< T >, Loyc.Collections.FVList< T >, Loyc.Collections.FVList< T >, Loyc.Collections.VList< T >, Loyc.Collections.VList< T >, Loyc.Collections.Impl.InternalList< T >, Loyc.Collections.Impl.InternalList< T >, Loyc.Collections.WListBase< T >, Loyc.Collections.DList< T >, Loyc.UString, Loyc.UString, Loyc.Collections.ReversedList< T >, Loyc.Collections.ListSlice< T >, Loyc.Collections.ListSlice< T >, Loyc.Collections.StringSlice, Loyc.Collections.StringSlice, Loyc.Collections.Slice_< T >, Loyc.Collections.Slice_< T >, Loyc.Collections.ArraySlice< T >, Loyc.Collections.ArraySlice< T >, Loyc.Collections.NegListSlice< T >, Loyc.Collections.NegListSlice< T >, Loyc.Collections.NegListSlice< T >, Loyc.Collections.ListSourceAsList< T >, Loyc.Syntax.StreamCharSource, Loyc.Collections.Repeated< T >, Loyc.Collections.ListAsListSource< T >, Loyc.Collections.Repeated< T >, Loyc.Collections.EmptyList< T >, Loyc.Collections.ICharSource, and Loyc.Collections.Impl.ListSourceBase< T >.
T Loyc.Collections.IListSource< out T >.TryGet | ( | int | index, |
out bool | fail | ||
) |
Gets the item at the specified index, and does not throw an exception on failure.
index | An index in the range 0 to Count-1. |
fail | A flag that is set on failure. |
In my original design, the caller could provide a value to return on failure, but this would not allow T to be marked as "out" in C# 4. For the same reason, we cannot have a ref/out T parameter. Instead, the following extension methods are provided:
Implemented in Loyc.Collections.AListReverseView< K, T >, Loyc.Collections.AListBase< K, T >, Loyc.Collections.Impl.InternalDList< T >, Loyc.Collections.FVList< T >, Loyc.Collections.VList< T >, Loyc.Collections.Impl.InternalList< T >, Loyc.Collections.WListBase< T >, Loyc.UString, Loyc.Collections.DList< T >, Loyc.Collections.ReversedList< T >, Loyc.Collections.ListSlice< T >, Loyc.Collections.StringSlice, Loyc.Collections.Slice_< T >, Loyc.Collections.ArraySlice< T >, Loyc.Collections.NegListSlice< T >, Loyc.Collections.FWList< T >, Loyc.Syntax.StreamCharSource, Loyc.Collections.WList< T >, Loyc.Collections.ListSourceAsList< T >, Loyc.Collections.ListAsListSource< T >, Loyc.Collections.BufferedSequence< T >, Loyc.Collections.Repeated< T >, Loyc.Collections.ReversedListSource< T >, Loyc.Collections.EmptyList< T >, Loyc.Collections.ListSourceAsSparse< T >, and Loyc.Collections.Impl.ListSourceBase< T >.
Referenced by Loyc.Syntax.Les.LesLanguageService.Parse(), and Loyc.Ecs.EcsLanguageService.Parse().