Simple example - you have a method or a property that returns an IEnumerable and the caller is iterating over that in a foreach() loop. Should you always be using 'yield return' in your IEnumerable method? Is there ever a reason not to? While I understand that it may not always be necessary to, or even "better" (maybe it's a very small collection for example), is there ever a reason to actively avoid doing this?
The bit of code that got me thinking about this was a function I wrote very similar to the accepted answer in this thread - How do I loop through a date range?
You use a yield return statement to return each element one at a time. The sequence returned from an iterator method can be consumed by using a foreach statement or LINQ query. Each iteration of the foreach loop calls the iterator method.
As written it is thread safe but if you comment out the lock(_sync) in AllValues you should be able to verify that it is not thread safe by running it a few times.
The yield return statement returns one element at a time. The return type of yield keyword is either IEnumerable or IEnumerator . The yield break statement is used to end the iteration. We can consume the iterator method that contains a yield return statement either by using foreach loop or LINQ query.
The only difference between yield and return is whenever yield statement is encountered in a function, the execution of function is suspended and a value is send back to the caller but because of yield whenever the function is called again, the execution of function begin where it left off previously.
Iterator blocks perform a "live" evaluation each time they are iterated.
Sometimes, however, the behavior you want is for the results to be a "snapshot" at a point in time. In these cases you probably don't want to use yield return
, but instead return a List<>
or Set
, or some other persistent collection instead.
It's also unnecessary to use yield return
if you're dealing with query objects directly. This is often the case with LINQ queries - it's better to just return the IEnumerable<>
from the query rather than iterating and yield return
ing results yourself. For example:
var result = from obj in someCollection where obj.Value < someValue select new { obj.Name, obj.Value }; foreach( var item in result ) yield return item; // THIS IS UNNECESSARY.... // just return {result} instead...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With