IEnumerable IndexOutOfRangeException

use*_*242 4 c# ienumerable

我不知道为什么我会System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'使用这段代码

IEnumerable<char> query = "Text result";
string illegals = "abcet";

for (int i = 0; i < illegals.Length; i++)
{
    query = query.Where(c => c != illegals[i]);
}

foreach (var item in query)
{
    Console.Write(item);
}
Run Code Online (Sandbox Code Playgroud)

请有人解释我的代码有什么问题.

Jon*_*eet 11

问题是你的lambda表达式正在捕获变量i,但是直到循环之后才会执行委托.到表达式c != illegals[i]执行时,iillegals.Length,因为那是最终的值i.重要的是要理解lambda表达式捕获变量,而不是"将lambda表达式转换为委托时这些变量的值".

以下是修复代码的五种方法:

选项1:i的本地副本

将值复制i到循环内的局部变量中,以便循环的每次迭代都捕获lambda表达式中的新变量.循环执行的其余部分不会更改新变量.

for (int i = 0; i < illegals.Length; i++)
{
    int copy = i;
    query = query.Where(c => c != illegals[copy]);
}
Run Code Online (Sandbox Code Playgroud)

选项2:在lambda表达式之外提取非法[i]

提取illegals[i]循环中的值(在lambda表达式之外)并在lambda表达式中使用该值.同样,变化的值i不会影响变量.

for (int i = 0; i < illegals.Length; i++)
{
    char illegal = illegals[i];
    query = query.Where(c => c != illegal);
}
Run Code Online (Sandbox Code Playgroud)

选项3:使用foreach循环

此选项仅适用于C#5及更高版本的编译器,作为C#5中foreach更改(更好)的含义.

foreach (char illegal in illegals)
{
    query = query.Where(c => c != illegal);
}
Run Code Online (Sandbox Code Playgroud)

选项4:使用Except一次

LINQ提供了一种执行集排除的方法:Except.这与之前的选项并不完全相同,因为您只会在输出中获得任何特定字符的单个副本.因此,如果e没有illegals,你会得到"Tex resul"的结果与上述选项,但"Tex rsul"使用Except.值得了解的是:

// Replace the loop entirely with this
query = query.Except(illegals);
Run Code Online (Sandbox Code Playgroud)

选项5:使用Contains一次

您可以Where使用lambda表达式调用一次,该表达式调用Contains:

// Replace the loop entirely with this
query = query.Where(c => !illegals.Contains(c));
Run Code Online (Sandbox Code Playgroud)