Ответ 1
Фактически вы не используете результат ReturnOne
. Вы вызываете метод и игнорируете возвращаемое значение... что означает, что вы никогда не увидите какой-либо из вашего кода, который будет запущен. Вы можете сделать это следующим образом:
static IEnumerable<int> OneThroughFive()
{
foreach (int x in ReturnOne())
{
yield x;
}
yield return 2;
yield return 3;
yield return 4;
yield return 5;
}
С# не имеет (в настоящее время хотя бы:) имеет своего рода конструкцию "yield all".
Тот факт, что вы не входите в него, не имеет никакого отношения к тому факту, что вы получили вызов внутри блока итератора - это просто так, пока вы не начнете использовать результат блока итератора, ни один из код запускается. Вот почему вам нужно отделить аргументацию от уступки. Например, рассмотрите этот код:
public IEnumerator<string> ReturnSubstrings(string x)
{
if (x == null)
{
throw ArgumentNullException();
}
for (int i = 0; i < x.Length; i++)
{
yield return x.Substring(i);
}
}
...
ReturnSubstring(null); // No exception thrown
Вам нужно написать это следующим образом:
public IEnumerator<string> ReturnSubstrings(string x)
{
if (x == null)
{
throw ArgumentNullException();
}
return ReturnSubstringsImpl(x);
}
private IEnumerator<string> ReturnSubstringsImpl(string x)
{
for (int i = 0; i < x.Length; i++)
{
yield return x.Substring(i);
}
}
Подробнее см. главу 6 С# в разделе "Глубина" - которая является бесплатной главой в первом издании:) Возьмите ее здесь.