Можно ли продвинуть перечислитель и получить его значение в виде лямбды?
Вопрос
Если у меня есть переменная IEnumerator, возможно ли иметь лямбда-функцию, которая принимает ее, продвигает с помощью MoveNext() и возвращает текущее значение при каждом ее вызове?
Решение
e => e.MoveNext() ? e.Current : null
Это продвинет перечислитель вперед и вернет текущее значение, а также вернет null, когда перечисление будет завершено.
Другие советы
Лямбда-выражение может содержать сложные операторы, поэтому вы можете выполнить следующее:
Func<IEnumerator, object> f = ie => { ie.MoveNext(); return ie.Current; };
Это то, что вы ищете?
List<string> strings = new List<string>()
{
"Hello", "I", "am", "a", "list", "of", "strings."
};
IEnumerator<string> e = strings.GetEnumerator();
Func<string> f = () => e.MoveNext() ? e.Current : null;
for (; ; )
{
string str = f();
if (str == null)
break;
Console.Write(str + " ");
}
Смысл в том, чтобы IEnumerator
это значит, что у вас уже есть синтаксический сахар, чтобы справиться с этим:
foreach (string str in strings)
Console.Write(str + " ");
Даже непосредственное обращение со счетчиком в этом случае выглядит более чистым:
while (e.MoveNext())
Console.Write(e.Current + " ");
Расширяя решение Abe, вы также можете использовать замыкания для хранения ссылки на перечислитель:
var iter = ((IEnumerable<char>)"hello").GetEnumerator();
//with closure
{
Func<object> f =
() =>
{
iter.MoveNext();
return iter.Current;
};
Console.WriteLine(f());
Console.WriteLine(f());
}
//without closure
{
Func<IEnumerator, object> f =
ie =>
{
ie.MoveNext();
return ie.Current;
};
Console.WriteLine(f(iter));
Console.WriteLine(f(iter));
}
Не связан с StackOverflow