序列不包含任何元素

Geo*_*vos 5 c# linq random

有人可以解释为什么以下LINQ查询抛出InvalidOperationException?
(不要说列表中没有元素,我正在寻找的值总是存在于集合中)

class Program
{
     static int lastNumber;
     static void Main()
     {
          int loopCount = 100; int minValue = 1; int maxValue = 10000;
          var numbers = Enumerable.Range(minValue, maxValue).ToList();//or ToArray();
          Random random = new Random();

          for (int i = 0; i < loopCount; i++)
          {
              //.First() throws the exception but it is obvious that the value exists in the list
              int x = numbers.Where(v => v == NewMethod(minValue, maxValue, random)).First();
          }
          Console.WriteLine("Finished");
          Console.ReadLine();

     }

     private static int NewMethod(int minValue, int maxValue, Random random)
     {
         var a1 = random.Next(minValue + 1, maxValue - 1);
         lastNumber = a1;
         return a1;
     }
}
Run Code Online (Sandbox Code Playgroud)

只有当我在lambda exssion中调用NewMethod时才会出现问题.
如果这样做有效

int temp=NewMethod(minValue, maxValue, random);
int x = numbers.Where(v => v == temp).First();
Run Code Online (Sandbox Code Playgroud)

我添加了lastNumber字段以帮助调试代码,您可以看到该值在崩溃时存在于集合中

PS
问题不是随机变量,我删除了参数并在方法中创建了一个新的局部随机但问题仍然存在

更新

事实证明,你不需要循环使其崩溃.如果多次运行程序,则会再次出现错误

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
class Program
{
    static int lastNumber;
    static void Main()
    {
        int minValue = 1, maxValue = 100000;
        var numbers = Enumerable.Range(minValue, maxValue).ToArray();
        //Crashes sometimes
        int x = numbers.Where(v => v == NewMethod(minValue, maxValue)).First();
        Console.WriteLine("Finished");
        Console.ReadLine();
     }

     private static int NewMethod(int minValue, int maxValue)
     {
          Random random = new Random();
          var a1 = random.Next(minValue + 1, maxValue - 1);
          lastNumber = a1;
          return a1;
      }
 }
Run Code Online (Sandbox Code Playgroud)

D S*_*ley 5

@Oleg是对的,但这就是问题的原因.

Where扫描列表,查找符合给定条件的元素.在这种情况下的标准对于每个元件改变.如果您将问题缩小,请说出包含5个元素的数组:

List<Int32> (5 items)
1 
2 
3 
4 
5 
Run Code Online (Sandbox Code Playgroud)

然后循环查找匹配某个随机数的值(x是Item[i]并且r是随机数):

Item 1: x = 1, r = 2  // fail
Item 2: x = 2, r = 3  // fail
Item 3: x = 3, r = 2  // fail
Item 4: x = 4, r = 3  // fail
Item 5: x = 5, r = 2  // fail
Run Code Online (Sandbox Code Playgroud)

请注意,没有项目匹配该特定随机数,因此没有项目符合条件并First引发异常!

正如您所发现的,修复是在枚举之前生成随机数:

int temp=NewMethod(minValue, maxValue, random);  // say 2

Item 1: x = 1, temp = 2  // fail
Item 2: x = 2, temp = 2  // success!
Run Code Online (Sandbox Code Playgroud)

边注:

maxValue在这里使用有点误导:

 Enumerable.Range(minValue, maxValue)
Run Code Online (Sandbox Code Playgroud)

由于第二个参数to Enumerable.Range是结果集合的长度,而不是最大值.在这种情况下,它起作用是因为你从1开始,但如果你使用了99和100,那么结果会出乎意料 - 你会得到99到198的范围.