【问题标题】:Why does it hang indefinitely?为什么会无限期挂?
【发布时间】:2021-02-14 18:07:01
【问题描述】:

我想知道为什么这段代码永远不会完成它的执行。

它利用MoreLinq

void Main()
{
    var values = MoreEnumerable.Random(1, 200);
    var filtered = MyMethod(values)
    .Take(2)
    .Dump();
}

public IEnumerable<int> MyMethod(IEnumerable<int> source) 
{
    return source
    .Select(x => new[] { x })
    .Aggregate((a, b) => new[] { a.Last() + b.First()});
}

【问题讨论】:

    标签: c# .net linq infinite-loop


    【解决方案1】:

    因为MoreEnumerable.Random(1, 200) 返回一个无限序列,而MyMethod 中的.Aggregate 语句试图枚举整个序列。

    如果我正确理解您要做什么,将 Take 移动到 MyMethod 可能会起作用:

    public static IEnumerable<int> MyMethod(IEnumerable<int> source)
    {
        return source
        .Select(x => new[] { x })
        .Take(2)
        .Aggregate((a, b) => new[] { a.Last() + b.First() });
    }
    

    【讨论】:

      【解决方案2】:

      我发现这个方法(.Random(1, 200)) 使用标准的 .NET 随机数生成器返回一个无限的随机整数序列。 Documentation

      【讨论】:

      • 我倾向于以同样的方式回答,不幸的是,两行之后的 .Take(2) 语句应该保留整个无限列表以进行枚举。我怀疑聚合是罪魁祸首...我正在逐步检查。
      • 您是否尝试在 MoreEnumerable.Random(1, 200).Take(2) 之后调用 Take()?
      【解决方案3】:

      MoreEnumerable.Random 枚举一个无限的随机整数列表,这就是原因。

      你必须替换

      var values = MoreEnumerable.Random(1, 200);
      

      通过有限列表:

      var values = MoreEnumerable.Random(1, 200).Take(100);
      

      由于我还不知道的原因,聚合似乎占据了整个列表,尽管你把 .Take(2) 放在两行之后。

      【讨论】:

      • "For reason I don't know..." 因为聚合是针对整个序列,而不是子序列(Take(n) before Aggregate 创建一个 n 的序列,这是一个新的,全序列)。这个聚合器恰好正在创建一个新的可枚举,所以 Take 就在上面,但是 Aggregate 在它的源耗尽之前不会返回......这永远不会
      • 是的,这就是我的怀疑。由于这种不太可能的行为,我自己也会陷入这个陷阱。 codeblog.jonskeet.uk/2010/12/30/…
      猜你喜欢
      • 2021-09-14
      • 2011-05-11
      • 1970-01-01
      • 2017-10-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多