Если я ступаю через следующий код, вызов к ReturnOne () пропускается.
static IEnumerable<int> OneThroughFive()
{
ReturnOne();
yield return 2;
yield return 3;
yield return 4;
yield return 5;
}
static IEnumerator<int> ReturnOne()
{
yield return 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;
}
В C# нет (в настоящее время, по крайней мере:) конструкции типа "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 книги C# in Depth - которая, как оказалось, является бесплатной главой в первом издании :) Возьмите ее здесь.