1- using System . Collections . Generic ;
1+ using System ;
2+ using System . Collections ;
3+ using System . Collections . Generic ;
24using System . Linq ;
35using JetBrains . Annotations ;
46using Linq . Extras . Internal ;
@@ -14,10 +16,39 @@ partial class XEnumerable
1416 /// <param name="source">The source sequence.</param>
1517 /// <returns>A sequence of elements paired with their index in the sequence.</returns>
1618 [ Pure ]
17- public static IEnumerable < IndexedItem < TSource > > WithIndex < TSource > (
19+ public static WithIndexEnumerable < TSource > WithIndex < TSource > (
1820 [ NotNull ] this IEnumerable < TSource > source )
1921 {
20- return source . Select ( ( item , index ) => new IndexedItem < TSource > ( item , index ) ) ;
22+ source . CheckArgumentNull ( nameof ( source ) ) ;
23+ return new WithIndexEnumerable < TSource > ( source ) ;
24+ }
25+
26+ /// <summary>
27+ /// Associates an index to each element of the source array.
28+ /// </summary>
29+ /// <typeparam name="TSource">The type of the elements of <c>source</c>.</typeparam>
30+ /// <param name="source">The source array.</param>
31+ /// <returns>A sequence of elements paired with their index in the array.</returns>
32+ [ Pure ]
33+ public static WithIndexArrayEnumerable < TSource > WithIndex < TSource > (
34+ [ NotNull ] this TSource [ ] source )
35+ {
36+ source . CheckArgumentNull ( nameof ( source ) ) ;
37+ return new WithIndexArrayEnumerable < TSource > ( source ) ;
38+ }
39+
40+ /// <summary>
41+ /// Associates an index to each element of the source <see cref="List{T}"/>.
42+ /// </summary>
43+ /// <typeparam name="TSource">The type of the elements of <c>source</c>.</typeparam>
44+ /// <param name="source">The source list.</param>
45+ /// <returns>A sequence of elements paired with their index in the list.</returns>
46+ [ Pure ]
47+ public static WithIndexListEnumerable < TSource > WithIndex < TSource > (
48+ [ NotNull ] this List < TSource > source )
49+ {
50+ source . CheckArgumentNull ( nameof ( source ) ) ;
51+ return new WithIndexListEnumerable < TSource > ( source ) ;
2152 }
2253
2354 /// <summary>
@@ -28,9 +59,222 @@ public static IEnumerable<IndexedItem<TSource>> WithIndex<TSource>(
2859 /// <returns>A sequence of elements without their associated indexes.</returns>
2960 [ Pure ]
3061 public static IEnumerable < TSource > WithoutIndex < TSource > (
31- [ NotNull ] this IEnumerable < IndexedItem < TSource > > source )
62+ [ NotNull ] this IEnumerable < ItemWithIndex < TSource > > source )
3263 {
3364 return source . Select ( indexed => indexed . Item ) ;
3465 }
66+
67+ /// <summary>
68+ /// A sequence of elements associated with their index.
69+ /// </summary>
70+ /// <typeparam name="TSource">The type of the elements of the source sequence.</typeparam>
71+ public struct WithIndexEnumerable < TSource > : IEnumerable < ItemWithIndex < TSource > >
72+ {
73+ private readonly IEnumerable < TSource > _source ;
74+
75+ internal WithIndexEnumerable ( IEnumerable < TSource > source )
76+ {
77+ _source = source ;
78+ }
79+
80+ /// <summary>
81+ /// Returns an enumerator that iterates through the <see cref="WithIndexEnumerable{TSource}"/>.
82+ /// </summary>
83+ /// <returns>An enumerator that iterates through the <see cref="WithIndexEnumerable{TSource}"/>.</returns>
84+ public Enumerator GetEnumerator ( ) => new Enumerator ( _source . GetEnumerator ( ) ) ;
85+
86+ IEnumerator < ItemWithIndex < TSource > > IEnumerable < ItemWithIndex < TSource > > . GetEnumerator ( ) => GetEnumerator ( ) ;
87+
88+ IEnumerator IEnumerable . GetEnumerator ( ) => GetEnumerator ( ) ;
89+
90+ /// <summary>
91+ /// Enumerates the elements of a <see cref="WithIndexEnumerable{TSource}"/>.
92+ /// </summary>
93+ public struct Enumerator : IEnumerator < ItemWithIndex < TSource > >
94+ {
95+ private readonly IEnumerator < TSource > _innerEnumerator ;
96+ private int _index ;
97+
98+ internal Enumerator ( IEnumerator < TSource > inner )
99+ {
100+ _innerEnumerator = inner ;
101+ _index = - 1 ;
102+ }
103+
104+ /// <summary>
105+ /// Advances the enumerator to the next element of the <see cref="WithIndexEnumerable{TSource}"/>.
106+ /// </summary>
107+ /// <returns>true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.</returns>
108+ public bool MoveNext ( )
109+ {
110+ if ( _innerEnumerator . MoveNext ( ) )
111+ {
112+ _index ++ ;
113+ return true ;
114+ }
115+
116+ return false ;
117+ }
118+
119+ void IEnumerator . Reset ( ) => _innerEnumerator . Reset ( ) ;
120+
121+ /// <summary>
122+ /// Releases all resources used by the <see cref="Enumerator"/>.
123+ /// </summary>
124+ public void Dispose ( ) => _innerEnumerator . Dispose ( ) ;
125+
126+ /// <summary>
127+ /// Gets the element at the current position of the enumerator.
128+ /// </summary>
129+ public ItemWithIndex < TSource > Current => new ItemWithIndex < TSource > ( _innerEnumerator . Current , _index ) ;
130+
131+ object IEnumerator . Current => Current ;
132+ }
133+ }
134+
135+ /// <summary>
136+ /// A sequence of elements associated with their index, optimized for the case when the underlying collection is an array.
137+ /// </summary>
138+ /// <typeparam name="TSource">The type of the elements of the source array.</typeparam>
139+ public struct WithIndexArrayEnumerable < TSource > : IEnumerable < ItemWithIndex < TSource > >
140+ {
141+ private readonly TSource [ ] _array ;
142+
143+ internal WithIndexArrayEnumerable ( TSource [ ] array )
144+ {
145+ _array = array ;
146+ }
147+
148+ /// <summary>
149+ /// Returns an enumerator that iterates through the <see cref="WithIndexArrayEnumerable{TSource}"/>.
150+ /// </summary>
151+ /// <returns>An enumerator that iterates through the <see cref="WithIndexArrayEnumerable{TSource}"/>.</returns>
152+ public Enumerator GetEnumerator ( ) => new Enumerator ( _array ) ;
153+
154+ IEnumerator < ItemWithIndex < TSource > > IEnumerable < ItemWithIndex < TSource > > . GetEnumerator ( ) => GetEnumerator ( ) ;
155+
156+ IEnumerator IEnumerable . GetEnumerator ( ) => GetEnumerator ( ) ;
157+
158+ /// <summary>
159+ /// Enumerates the elements of a <see cref="WithIndexArrayEnumerable{TSource}"/>.
160+ /// </summary>
161+ public struct Enumerator : IEnumerator < ItemWithIndex < TSource > >
162+ {
163+ private readonly TSource [ ] _array ;
164+ private int _index ;
165+
166+ internal Enumerator ( TSource [ ] array )
167+ {
168+ _array = array ;
169+ _index = - 1 ;
170+ }
171+
172+ /// <summary>
173+ /// Advances the enumerator to the next element of the <see cref="WithIndexArrayEnumerable{TSource}"/>.
174+ /// </summary>
175+ /// <returns>true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.</returns>
176+ public bool MoveNext ( )
177+ {
178+ if ( _index + 1 < _array . Length )
179+ {
180+ _index ++ ;
181+ return true ;
182+ }
183+
184+ return false ;
185+ }
186+
187+ void IEnumerator . Reset ( )
188+ {
189+ _index = - 1 ;
190+ }
191+
192+ /// <summary>
193+ /// Releases all resources used by the <see cref="Enumerator"/>.
194+ /// </summary>
195+ public void Dispose ( )
196+ {
197+ }
198+
199+ /// <summary>
200+ /// Gets the element at the current position of the enumerator.
201+ /// </summary>
202+ public ItemWithIndex < TSource > Current => new ItemWithIndex < TSource > ( _array [ _index ] , _index ) ;
203+
204+ object IEnumerator . Current => throw new NotImplementedException ( ) ;
205+ }
206+ }
207+
208+ /// <summary>
209+ /// A sequence of elements associated with their index, optimized for the case when the underlying collection is a <see cref="List{T}"/>.
210+ /// </summary>
211+ /// <typeparam name="TSource">The type of the elements of the source list.</typeparam>
212+ public struct WithIndexListEnumerable < TSource > : IEnumerable < ItemWithIndex < TSource > >
213+ {
214+ private readonly List < TSource > _list ;
215+
216+ internal WithIndexListEnumerable ( List < TSource > list )
217+ {
218+ _list = list ;
219+ }
220+
221+ /// <summary>
222+ /// Returns an enumerator that iterates through the <see cref="WithIndexListEnumerable{TSource}"/>.
223+ /// </summary>
224+ /// <returns>An enumerator that iterates through the <see cref="WithIndexListEnumerable{TSource}"/>.</returns>
225+ public Enumerator GetEnumerator ( ) => new Enumerator ( _list . GetEnumerator ( ) ) ;
226+
227+ IEnumerator < ItemWithIndex < TSource > > IEnumerable < ItemWithIndex < TSource > > . GetEnumerator ( ) => GetEnumerator ( ) ;
228+
229+ IEnumerator IEnumerable . GetEnumerator ( ) => GetEnumerator ( ) ;
230+
231+ /// <summary>
232+ /// Enumerates the elements of a <see cref="WithIndexListEnumerable{TSource}"/>.
233+ /// </summary>
234+ public struct Enumerator : IEnumerator < ItemWithIndex < TSource > >
235+ {
236+ private List < TSource > . Enumerator _inner ;
237+ private int _index ;
238+
239+ internal Enumerator ( List < TSource > . Enumerator inner )
240+ {
241+ _inner = inner ;
242+ _index = - 1 ;
243+ }
244+
245+ /// <summary>
246+ /// Advances the enumerator to the next element of the <see cref="WithIndexListEnumerable{TSource}"/>.
247+ /// </summary>
248+ /// <returns>true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.</returns>
249+ public bool MoveNext ( )
250+ {
251+ if ( _inner . MoveNext ( ) )
252+ {
253+ _index ++ ;
254+ return true ;
255+ }
256+
257+ return false ;
258+ }
259+
260+ void IEnumerator . Reset ( )
261+ {
262+ _index = - 1 ;
263+ ( ( IEnumerator ) _inner ) . Reset ( ) ;
264+ }
265+
266+ /// <summary>
267+ /// Releases all resources used by the <see cref="Enumerator"/>.
268+ /// </summary>
269+ public void Dispose ( ) => _inner . Dispose ( ) ;
270+
271+ /// <summary>
272+ /// Gets the element at the current position of the enumerator.
273+ /// </summary>
274+ public ItemWithIndex < TSource > Current => new ItemWithIndex < TSource > ( _inner . Current , _index ) ;
275+
276+ object IEnumerator . Current => throw new NotImplementedException ( ) ;
277+ }
278+ }
35279 }
36280}
0 commit comments