Метод с помощью возврат урожая должен быть объявлен как возврат одного из следующих двух интерфейсов:
IEnumerable<SomethingAppropriate>
IEnumerator<SomethingApropriate>
(спасибо Jon и Marc для указания на IEnumerator)
Пример:
public IEnumerable<AClass> YourMethod()
{
foreach (XElement header in headersXml.Root.Elements())
{
yield return (ParseHeader(header));
}
}
урожай является ленивым производителем данных, только производя другой объект после того, как первое было получено, тогда как возврат списка возвратит все сразу.
, Таким образом, существует различие, и необходимо объявить метод правильно.
Для получения дополнительной информации читавший ответ Jon здесь , который содержит некоторые очень полезные ссылки.
Это - хитрая тема. Короче говоря это - простой способ реализовать IEnumerable и его друзей. Компилятор создает Вас конечный автомат, преобразовывая параметры и локальные переменные в переменные экземпляра в новом классе. Сложный материал.
у меня есть несколько ресурсов на этом:
"урожай" создает блок итератора - компилятор генерировал класс, который может реализовать или IEnumerable[<T>]
или IEnumerator[<T>]
. У Jon Skeet есть очень хорошее (и свободный) обсуждение этого в главе 6 C# подробно .
, Но в основном - для использования "урожая" метод должен возвратиться IEnumerable[<T>]
или IEnumerator[<T>]
. В этом случае:
public IEnumerable<AClass> SomeMethod() {
// ...
foreach (XElement header in headersXml.Root.Elements()){
yield return (ParseHeader(header));
}
}
Список реализует Ienumerable.
Вот пример, который мог бы пролить некоторый свет на то, что Вы пытаетесь изучить. Я записал этому приблизительно 6 месяцев
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace YieldReturnTest
{
public class PrimeFinder
{
private Boolean isPrime(int integer)
{
if (0 == integer)
return false;
if (3 > integer)
return true;
for (int i = 2; i < integer; i++)
{
if (0 == integer % i)
return false;
}
return true;
}
public IEnumerable<int> FindPrimes()
{
int i;
for (i = 1; i < 2147483647; i++)
{
if (isPrime(i))
{
yield return i;
}
}
}
}
class Program
{
static void Main(string[] args)
{
PrimeFinder primes = new PrimeFinder();
foreach (int i in primes.FindPrimes())
{
Console.WriteLine(i);
Console.ReadLine();
}
Console.ReadLine();
Console.ReadLine();
}
}
}
Я настоятельно рекомендую использование Отражатель , чтобы взглянуть на то, что yield
на самом деле делает для Вас. Вы будете в состоянии видеть полный код класса, который компилятор генерирует для Вас при использовании урожая, и я нашел, что люди понимают понятие намного более быстро, когда они видят результат низкого уровня (хорошо, среднего уровня, я предполагаю).
Что делает метод, который Вы используете, это в похоже? Я не думаю, что это может использоваться в просто цикле отдельно.
, Например...
public IEnumerable<string> GetValues() {
foreach(string value in someArray) {
if (value.StartsWith("A")) { yield return value; }
}
}