1

I am learning linq throught decompiling the System.Core.dll (4.7.3429.0) by dnSpy and see duplicated 'yield break;' in several cases, like this one

private static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source)
    {
        foreach (object obj in source)
        {
            yield return (TResult)((object)obj);
        }
        IEnumerator enumerator = null;
        yield break;
        yield break;
    }

Will the second one never be called?

What is it purpose? Does it a bag in dnSpy or missusing in .NET?

Kamerton
  • 315
  • 3
  • 9
  • 1
    This is unrelated to your question, but reading through decompiled code may not be the best approach to learning LINQ, especially when there is reference source available. – Jonathon Chase Jul 11 '19 at 21:00
  • A method like this gets compiled to a state-machine, a decompiler has to attempt to not only decompile the CIL but turn that state-machine back into the original method with varying degrees of freedom. Obviously in this case its not doing it right to our eyes, but its still technically correct and the end of that method would get optimized away. take a look at the how the compiler actually creates this state-machine at https://sharplab.io/ – TheGeneral Jul 11 '19 at 21:23
  • @JonathonChase Can you add the refference please?) – Kamerton Jul 15 '19 at 10:43

3 Answers3

3

That's likely just the dnSpy decompiler making wild guesses at what I'm assuming is release optimized code.

Another decompiler yielded the following:

private static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source)
{
  foreach (TResult result in source)
    yield return result;
}

Which seems a more sane representation.

To your question on yield break;, once it hits the first one the iterator is done. Most IDE's can flag any code following it as unreachable.

Jonathon Chase
  • 9,396
  • 21
  • 39
3

Yep, bug. Both reference source and Telerik's JustDecompile simply show

foreach (object obj in source) yield return (TResult)obj;

(JustDecompile adds braces).

Both yield break statements are redundant. And IEnumerator enumerator = null; is a redundant statement as well.

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
1

There is no purpose having yield break twice. It is somehow similar to having return statement twice in a row, one of them will be unreachable...

The purpose of yield break is to end the iterator.

Johnny
  • 8,939
  • 2
  • 28
  • 33