2

I have this inside of a do..while:

yield return string.Join(",", arr) + "\n";

Why isn't the compiler complaining that not all of the code paths are returning a value?

The full code example is below:

    public static IEnumerable<string> Convert(Stream stream)
    {
        System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);

        IExcelDataReader reader = ExcelReaderFactory.CreateBinaryReader(stream);
        var csvContent = string.Empty;
        do
        {
            while (reader.Read())
            {
                var arr = new List<string>();
                for (int i = 0; i < reader.FieldCount; i++)
                {
                    var cell = reader[i]?.ToString();
                    var format = reader.GetNumberFormatString(i);
                    if (format == "mm\\/dd\\/yyyy" || format == "M/d/yyyy")
                    {
                        cell = cell.Replace(" 12:00:00 AM", "");
                    }
                    if (format == "h\\:mm\\:ss AM/PM")
                    {
                        cell = cell.Replace("12/31/1899 ", "");
                    }
                    var processedCell = cell == null ? string.Empty : cell.Contains(",") ? "\"" + cell + "\"" : cell;
                    arr.Add(processedCell);
                }
                yield return string.Join(",", arr) + "\n";
            }
        } while (reader.NextResult());
    }

There is no return keyword as the last line!

Alex Gordon
  • 57,446
  • 287
  • 670
  • 1,062
  • @DavidG exactly! and my signature is promising an `IEnumerable` return value, not a `void` ! – Alex Gordon Nov 23 '18 at 01:27
  • 1
    That is the nature of yield return. Check example from Microsoft. https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/yield#example If exponent is 0, it is the same as yours. – wannadream Nov 23 '18 at 01:29
  • 3
    Iterators march to a different drummer. Not returning anything is just fine, it returns an empty iterator. – Hans Passant Nov 23 '18 at 01:31
  • @HansPassant very nice explanation, but where does it say that? – Alex Gordon Nov 23 '18 at 01:32
  • 2
    The C# language specification, chapter 10.4.4.1. It doesn't exactly yell it out. – Hans Passant Nov 23 '18 at 01:36
  • In the link wannadream gave you it gives you a basic explanation, on that page there is also a link to the c# specification which goes in to more detail. – Scott Chamberlain Nov 23 '18 at 01:41
  • This chapter explains more: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/statements#the-yield-statement – wannadream Nov 23 '18 at 01:43

2 Answers2

4

This is an exception in connection with the IEnumerable iterator pattern and the yield return keyword. In this case, the compiler constructs its state machine for the iterator runtime, and does not apply the same set of path coverage as it does with linear methods.

The semantics goes, "an iterator that does not produce, is empty, and this is at the same time a valid substitution for any code path that does not explicitely return a value".

The key to understanding this is that the compiler reforms methods that constitute iterators, to code that does no longer have uninitialized return values. See C# standard chapter 10.4.4.1 for an example.

Related: https://stackoverflow.com/a/9631242/1132334

Cee McSharpface
  • 8,493
  • 3
  • 36
  • 77
0

Because you are using yield return. yield return method ends not with return, but actually with yield break and last yield break can be omitted

UPD. This is example of old code (Robotics Studio and Unity) where yield break on last line is exists enter image description here enter image description here

Alexei Shcherbakov
  • 1,125
  • 13
  • 10
  • 1
    "last yield break can be omitted" - What? No. That's not right. – Enigmativity Nov 23 '18 at 01:41
  • I've updated answer with code sample from book ~2008 year. – Alexei Shcherbakov Nov 23 '18 at 01:56
  • 2
    Thanks for posting an answer. Please beware that pictures of code are frowned upon on SO because one can't copy/paste to try it. Could you please update your answer? – Jacques Gaudin Nov 23 '18 at 08:30
  • How do you qualify “frowned upon” when this is the accepted answer? – Alex Gordon Nov 23 '18 at 11:04
  • first code sample is from copyrighted book and second was founded by google image search. I remember that 'yield break' was necessary for Visual Studio more than 10 years ago (I even can't remember - Visual Studio 2005 Beta 2 or RTM), so this is only "historical" sample - in modern version of C# language it is not necessary. So I tried to find examples of 'yield break' in Internet in pre2005-2008 years :-) – Alexei Shcherbakov Nov 23 '18 at 20:18