2009-07-01 2 views

ответ

36

yield return работает ровно на 4-х случаях:

  • IEnumerable
  • IEnumerable<T>
  • IEnumerator
  • IEnumerator<T>

Это потому, что он должен построить государственную машину внутри; словарь (и т. д.) с этим невозможен. Вы можете, конечно, только return подходящего типа.

+0

Полезная статья здесь http://csharpindepth.com/articles/chapter6/iteratorblockimplementation.aspx, если вы хотите реализовать IEnumerable самостоятельно. – Rory

+0

@Rory да, сама реализация - это массивная PITA, и я не могу придумать никаких «нормальных» причин, когда-либо сделавших это, теперь, когда существуют блоки итераторов. У меня есть несколько таких, но обычно это совместимо с проектами, которые нужно строить даже на компиляторах C# 1.2; не совсем «нормальный» сценарий. –

+0

Согласен, хотя IGrouping может быть приятным, в некоторых случаях кажется более удобным использовать IEnumerable >, чтобы вы получили магию возврата доходности. – Rory

0

Неа, просто IEnumerable :-)

+0

Неверно; см. мой ответ ;-p –

1

Я не думаю, что так. В то время как точно не описывает это, способ, которым он сформулирован, подразумевает, что он может использоваться только тогда, когда тип возврата метода равен IEnumerable или IEnumerable<T>. Возможно, вы сможете написать класс, который реализует IGrouping с учетом IEnumerable (который будет возвращен из вашего метода с использованием yield return), но это единственный вариант.

+1

Спецификация языка говорит об этом вместо ... см. 8.18 в ECMA 334 –

2

Нет, поскольку блок итератора - это просто автомат, созданный от вашего имени компилятором. Эта функция позволяет вам «выдать» и элемент как часть последовательности.

Если тип возврата был отличным от IEnumerable<T> (например, IDictionary), то компилятор должен был бы генерировать методы для реализации этого интерфейса, и в этот момент это не имело бы большого смысла, потому что вы будете работать с коллекцией, а не с последовательность.

15

Вы могли бы вернуть IEnumerable<KeyValuePair<K,V>>, который будет похож на словарь. Затем вы получите доход KeyValuePairs. Вы можете даже обернуть это другим методом, который создает словарь из возврата. Единственное, что первый метод не гарантировал, - это уникальность в ключах.

+7

Затем вы теряете время доступа O (1) и должны циклически переключаться между каждым KVP, чтобы найти правильный ключ, принимая наихудшее время O (n). –

4

Ответ: Нет yield return заявление может быть использовано только если тип возвращаемого значения IEnumerator, IEnumerator<T>, IEnumerable или IEnumerable<T>.

От §8.14 из C# 3.0 spec:

Оператор выхода используется в блоке итератора (§8.2) с получением значения для объекта нумератора (§10.14.4) или перечислимый объект (§10.14.5) итератора или сигнализировать о завершении итерации.

От §10.14.4:

объекта Перечислителя имеет следующие характеристики:

  1. Он реализует IEnumerator и IEnumerator<T>, где T типа выхода итератора.

[...]

От §10.14.5:

Перечислимый объект имеет следующие характеристики:

  1. Он реализует IEnumerable и IEnumerable<T>, где T является типом выход итератора.

[...]

2

Просто вызовите метод итератора и цепь ToDictionary или GroupBy после него, и у вас есть почти то же самое. Поместите это в однострочный метод обертки, если вам нужно так называть его из нескольких мест.

-2

Как yield return может использоваться с типами IEnumerator<T> Почему бы не сделать что-нибудь подобное?

internal static IEnumerable<Dictionary<byte, string>> GetData() 
    { 
     Dictionary<byte, string> result = GetMyData(); //read from db 
     yield return result; 
    } 

Надеюсь, это поможет.

+0

Вы «получаете» список целых словарей, а не пар ключ-значение. – titol

Смежные вопросы