【问题标题】:Cannot evaluate expression c#无法评估表达式c#
【发布时间】:2017-05-10 05:50:04
【问题描述】:

我在var okColors = colors.ToArray(); 收到以下错误

无法计算表达式,因为当前线程处于堆栈溢出状态。

你能帮忙吗?

    private Color GetRandomColor()
    {
        Random randomGen = new Random();
        Color randomColor = Color.Red;

        KnownColor[] names = (KnownColor[])Enum.GetValues(typeof(KnownColor));
        KnownColor[] badColors = { KnownColor.AliceBlue };
        IEnumerable<KnownColor> colors = names.Except(badColors);

        var okColors = colors.ToArray();

        KnownColor randomColorName = okColors[randomGen.Next(okColors.Length)];
        randomColor = Color.FromKnownColor(randomColorName);
        if (!ColorsList.Contains(randomColor) && !randomColor.Name.Contains("Light"))
            ColorsList.Add(randomColor);
        else
            GetRandomColor();
        return randomColor;
    }

【问题讨论】:

  • 你能发布你的班级定义吗?
  • 我认为您对GetRandomColor 有无限递归,这会导致堆栈溢出。由于您每次调用该方法时都会创建一个新的Random,并且Random 是根据当前时间播种的,因此您的代码会一遍又一遍地选择相同的颜色并最终溢出堆栈。
  • 除了重复使用Random的问题之外,如果你生成太多颜色,你总是会遇到无限递归,因为找到的每种颜色都是ColorsList。即使您使用 random 解决问题,也会发生这种情况。
  • “KnownColor”的定义是?并且 '.Contains' 总是给出值数组,确保它不应该为空。

标签: c#


【解决方案1】:

您的代码抛出 StackOverflowException,当它发生时,调试器无法再评估任何变量,从而导致您看到的错误。

为什么代码有StackOverflowException

  • 代码使用错误的方式生成随机数,并以相同的数字结束足够的调用。正确方法 - How do I generate a random int number in C#? - 使用静态 Random 实例。
  • 因为.Contains 的结果检查不断失败,代码基本上变成了无限递归:

    private Color GetRandomColor()
    {
      if (true) return GetRandomColor();
    }
    

补充阅读:How do I prevent and/or handle a StackOverflowException?

【讨论】:

    【解决方案2】:

    对于每个递归调用,您必须使用相同的 Random 实例,不要在每个函数调用中创建一个新实例。如果每次调用函数时都会在函数中创建一个新的 Random 实例,那么您可能会一直获得相同的值,而不是您所期望的随机值。

    这里是another thread,你可能想看看:

    randomNumber 每次都会创建一个新的 Random 实例... turn 基于当前创建一个新的伪随机数生成器 时间......这并没有你想象的那么频繁。

    在链接的帖子中,Jon Skeet 还建议不要使用静态随机变量

    重复使用相同的 Random 实例...但不要“修复”它 创建一个静态随机变量。这在 长期来看,因为 Random 不是线程安全的。

    一种选择是将 Random 的实例作为参数传递给函数,这将确保沿递归链传递相同的 Random 实例:

    private Color GetRandomColor(Random randomGen = new Random())
    {
        Color randomColor = Color.Red;
    
        KnownColor[] names = (KnownColor[])Enum.GetValues(typeof(KnownColor));
        KnownColor[] badColors = { KnownColor.AliceBlue };
        IEnumerable<KnownColor> okColors = names.Except(badColors).ToArray();
    
        KnownColor randomColorName = okColors[randomGen.Next(okColors.Length)];
        randomColor = Color.FromKnownColor(randomColorName);
    
        if (!ColorsList.Contains(randomColor) && !randomColor.Name.Contains("Light"))
        {
            ColorsList.Add(randomColor);
        }
        else
        {
            GetRandomColor(randomGen);
        }
    
        return randomColor;
    }
    

    【讨论】:

      【解决方案3】:

      我认为您的代码不断地达到else 部分。 请检查您的if()..else() 条件

      【讨论】:

        【解决方案4】:

        以下功能将为您工作。

            List<Color> ColorsList = new List<Color>();
            private Color GetRandomColor(Random randomGen)
                    {
                        Color randomColor = Color.Red;
                        KnownColor[] names = (KnownColor[])Enum.GetValues(typeof(KnownColor));
                        KnownColor[] badColors = { KnownColor.AliceBlue };            
                        IEnumerable<KnownColor> colors = names.Except(badColors);
                        colors = colors.ToArray().Except(ColorsList.Select(x => x.ToKnownColor()));
                        KnownColor[] okColors = colors.ToArray();
                        KnownColor randomColorName = okColors[randomGen.Next(okColors.Length)];
                        randomColor = Color.FromKnownColor(randomColorName);
        
                        if (!ColorsList.Contains(randomColor))
                        {
                            ColorsList.Add(randomColor);
                            if (okColors.Count() == 1)
                            {
                                ColorsList.Clear();
                            }
                        }
                        else
                        {
                            GetRandomColor(randomGen);
                        }
        
                        return randomColor;
                    }
        

        调用这个函数

        GetRandomColor(new Random())
        

        如上所述,问题是由于 GetRandomColor 函数的无限递归调用。为了解决这个问题,我已经从 okColor 列表中删除了已经获取的随机颜色。同样在获得所有颜色后,我已经清除了 ColorsList 以继续随机化。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-26
          • 1970-01-01
          • 2015-01-17
          • 1970-01-01
          • 2018-10-20
          相关资源
          最近更新 更多