【问题标题】:why does the compiler NOT complain about not all paths returning?为什么编译器不抱怨并非所有路径都返回?
【发布时间】:2019-04-25 15:37:28
【问题描述】:

我在 do..while 里面有这个:

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

为什么编译器没有抱怨并非所有代码路径都返回值?

完整的代码示例如下:

    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());
    }

最后一行没有return关键字!

【问题讨论】:

  • @DavidG 完全正确!我的签名承诺返回值IEnumerable&lt;string&gt;,而不是void
  • 这就是收益回报的本质。检查来自 Microsoft 的示例。 docs.microsoft.com/en-us/dotnet/csharp/language-reference/…指数为0,和你的一样。
  • 迭代器向不同的鼓手前进。不返回任何东西就好了,它返回一个空的迭代器。
  • @HansPassant 很好的解释,但它是在哪里说的?
  • C# 语言规范,第 10.4.4.1 章。它并没有完全喊出来。

标签: c# .net visual-studio visual-studio-2017


【解决方案1】:

这是与IEnumerable 迭代器模式和yield return 关键字相关的一个例外。在这种情况下,编译器会为迭代器运行时构造其状态机,并且不会应用与线性方法相同的路径覆盖集。

语义是,“不产生的迭代器是空的,同时这也是对任何没有显式返回值的代码路径的有效替换”。

理解这一点的关键是编译器将构成迭代器的方法改造成不再具有未初始化返回值的代码。有关示例,请参见 C# 标准第 10.4.4.1 章。

相关:https://stackoverflow.com/a/9631242/1132334

【讨论】:

  • 换个说法,你同意hans吗?
  • 我们都同意规范。只是汉斯明明是心知肚明的,我得查查。
【解决方案2】:

因为您使用的是收益回报yield return 方法不是以 return 结束,而是以 yield break 结束,最后一个 yield break 可以省略

UPD。这是旧代码(Robotics Studio 和 Unity)的示例,其中存在最后一行的 yield break

【讨论】:

  • “可以省略最后的屈服中断” - 什么?不,这是不对的。
  • 我已经用 ~2008 年书中的代码示例更新了答案。
  • 感谢您发布答案。请注意,代码图片在 SO 上不受欢迎,因为无法复制/粘贴来尝试它。你能更新你的答案吗?
  • 当这是公认的答案时,您如何界定“皱眉”?
  • 第一个代码示例来自受版权保护的书籍,第二个是由谷歌图片搜索创建的。我记得 10 多年前 Visual Studio 需要“屈服中断”(我什至不记得 - Visual Studio 2005 Beta 2 或 RTM),所以这只是“历史”示例 - 在现代版本的 C# 语言中没有必要。所以我试图在 2005-2008 年之前在互联网上找到“收益中断”的例子:-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-06
  • 2012-04-24
  • 2014-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多