Can I use yield return
when the return type is an IGrouping<TKey, TElement>
or an IDictionary<TKey, TValue>
?

- 1,372
- 2
- 16
- 23

- 88,211
- 155
- 421
- 625
-
possible duplicate of [Some help understanding "yield"](http://stackoverflow.com/questions/317462/some-help-understanding-yield) – nawfal Jul 09 '14 at 06:54
8 Answers
yield return
works for exactly 4 cases:
IEnumerable
IEnumerable<T>
IEnumerator
IEnumerator<T>
This is because it has to build a state machine internally; a dictionary (etc) wouldn't be possible with this. You can of course just return
a suitable type instead.

- 1,026,079
- 266
- 2,566
- 2,900
-
Handy article here http://csharpindepth.com/articles/chapter6/iteratorblockimplementation.aspx if you want to implement IEnumerable yourself. – Rory Sep 16 '12 at 23:01
-
1@Rory yes, implementing it yourself is a massive PITA, and I can't think of any "normal" reasons to ever do so, now that iterator blocks exist. I have a few such, but that's usually for compatibility on projects that need to build even on C# 1.2 compilers; not exactly the "normal" scenario. – Marc Gravell Sep 17 '12 at 06:48
-
Agreed, although IGrouping could be nice in some cases it seems easier to use an IEnumerable
> instead so you get the magic of yield return. – Rory Sep 17 '12 at 10:25
You could however return IEnumerable<KeyValuePair<K,V>>
that would be similar to a dictionary. You would then yield return KeyValuePairs. You could even wrap this with another method that creates a dictionary out of the return. The only thing the first method would not guarantee is uniqueness in the keys.

- 15,459
- 7
- 44
- 62
-
11Then you lose the O(1) access time, and have to cycle through every single KVP to find the correct key, taking at worst O(n) times. – Callum Rogers Aug 18 '09 at 19:30
Answer: No. A yield return
statement can be used only if the return type is IEnumerator
, IEnumerator<T>
, IEnumerable
, or IEnumerable<T>
.
From §8.14 of the C# 3.0 spec:
The yield statement is used in an iterator block (§8.2) to yield a value to the enumerator object (§10.14.4) or enumerable object (§10.14.5) of an iterator or to signal the end of the iteration.
From §10.14.4:
An enumerator object has the following characteristics:
- It implements
IEnumerator
andIEnumerator<T>
, whereT
is the yield type of the iterator.
[...]
From §10.14.5:
An enumerable object has the following characteristics:
- It implements
IEnumerable
andIEnumerable<T>
, whereT
is the yield type of the iterator.
[...]

- 236,483
- 35
- 423
- 525
No, because an iterator block is simply a state machine built on your behalf by the compiler. This feature allows you to "yield" and item as a portion of a sequence.
If the return type was other than IEnumerable<T>
(like IDictionary
for example) the compiler would have to generate methods to implement that interface and at that point it wouldn't make much sense because you would be working with a collection rather than a sequence.

- 344,730
- 71
- 640
- 635
Just call the iterator method and chain ToDictionary
or GroupBy
after it, and you have much the same thing. Put that in a one-line wrapper method if you need to call it like that from several places.

- 114,894
- 38
- 205
- 284
I don't think so. While the documentation doesn't exactly spell it out, the way it is worded implies that it can only be used when the return type of the method is either IEnumerable
or IEnumerable<T>
. You might be able to write a class that implements IGrouping
given an IEnumerable
(that would be returned from your method using yield return
), but that's about the only option really.

- 30,088
- 6
- 78
- 89
you can always create a IAsyncEnumerable<KeyValuePair<T,V>> using a repository or list and yield return new KeyValuePair<T,V>(obj1,obj2); and a second function to call the method above that returns 'IAsyncEnumerable<KeyValuePair<T,V>>' add into a dictionary and add to the dictionary if (!dic.TryGetValue(output.Key,out object s)) assuming you want unique keys

- 185
- 2
- 15