Давайте рассмотрим ваш код подробно, кроме небольшой опечатки, которая stuff<T>
должна быть классом, ваша реализация IEnumerator<T>
выглядит следующим образом:
public IEnumerator<T> GetEnumerator()
{
lock (Sync)
using (IEnumerator<T> safeEnum = TObjects.AsEnumerable().GetEnumerator())
while (safeEnum.MoveNext())
yield return safeEnum.Current;
}
Это реализация для Enumeration
, а не просто Enumerator
, поскольку после получения Enumerator вы продолжаете обрабатывать коллекцию, перемещая Enumerator дальше, в идеале ваша пользовательская реализация должна выглядеть следующим образом:
IEnumerator IEnumerable.GetEnumerator() => TObjects.AsEnumerable().GetEnumerator()
, поскольку перечисление выполненос помощью цикла foreach
, который делает это путем доступа к реализованному перечислителю и вызова метода MoveNext
и свойства Current
, поэтому текущая реализация могла бы быть более краткой
Реализация перечислителя
TObjects.AsEnumerable().GetEnumerator()
реализация выглядит следующим образом, она обращается к реализации GetEnumerator()
для статического класса System.Linq.Enumerable
, который внутренне имеет реализацию абстрактного класса Iterator<T>
.
AsEnumerable()
- это простой метод расширения
public static IEnumerable<TSource> AsEnumerable<TSource>(this IEnumerable<TSource>
source)
{
return source;
}
Теперь, поскольку наш источник является массивом T[]
, мы являемсяприменяя предложение Where
, следовательно, как указано в следующей реализации Enumerable
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
if (source is Iterator<TSource>) return ((Iterator<TSource>)source).Where(predicate);
if (source is TSource[]) return new WhereArrayIterator<TSource>((TSource[])source, predicate);
if (source is List<TSource>) return new WhereListIterator<TSource>((List<TSource>)source, predicate);
return new WhereEnumerableIterator<TSource>(source, predicate);
}
Мы получаем WhereArrayIterator
, реализация которого для перечисления / итерации следующая:
class WhereArrayIterator<TSource> : Iterator<TSource>
{
TSource[] source;
Func<TSource, bool> predicate;
int index;
public WhereArrayIterator(TSource[] source, Func<TSource, bool> predicate) {
this.source = source;
this.predicate = predicate;
}
public override Iterator<TSource> Clone() {
return new WhereArrayIterator<TSource>(source, predicate);
}
public override bool MoveNext() {
if (state == 1) {
while (index < source.Length) {
TSource item = source[index];
index++;
if (predicate(item)) {
current = item;
return true;
}
}
Dispose();
}
return false;
}
public override IEnumerable<TResult> Select<TResult>(Func<TSource, TResult> selector) {
return new WhereSelectArrayIterator<TSource, TResult>(source, predicate, selector);
}
public override IEnumerable<TSource> Where(Func<TSource, bool> predicate) {
return new WhereArrayIterator<TSource>(source, CombinePredicates(this.predicate, predicate));
}
}
Как уже упоминалось в комментариях, получение перечислителя в коллекцию является потокобезопасным, так как доступно только для чтения.Все упомянутые сведения о коде и классе можно найти в справочном источнике MS , который имеет поисковый браузер API