首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IEnumerable IndexOutOfRangeException

IEnumerable IndexOutOfRangeException
EN

Stack Overflow用户
提问于 2018-09-30 06:48:04
回答 2查看 605关注 0票数 4

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

代码语言:javascript
复制
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);
}

请有人解释一下我的密码出了什么问题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-09-30 06:52:29

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

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

选项1: i的本地副本

i的值复制到循环中的局部变量中,以便循环的每一次迭代都在lambda表达式中捕获一个新变量。这个新变量不会被循环执行的其余部分所改变。

代码语言:javascript
复制
for (int i = 0; i < illegals.Length; i++)
{
    int copy = i;
    query = query.Where(c => c != illegals[copy]);
}

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

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

代码语言:javascript
复制
for (int i = 0; i < illegals.Length; i++)
{
    char illegal = illegals[i];
    query = query.Where(c => c != illegal);
}

选项3:使用foreach循环

此选项仅适用于C# 5和更高版本的编译器,因为foreach的含义在C# 5中发生了变化(更好)。

代码语言:javascript
复制
foreach (char illegal in illegals)
{
    query = query.Where(c => c != illegal);
}

Except 选项4:使用 once

LINQ提供了一种执行集排除的方法:Except。但是,这与前面的选项不太一样,因为输出中只有一个特定字符的副本。因此,如果e不在illegals中,您将得到使用上述选项的"Tex resul“的结果,而使用Except的则是"Tex rsul”。不过,值得知道的是:

代码语言:javascript
复制
// Replace the loop entirely with this
query = query.Except(illegals);

选项5:使用 once

您可以调用Where一次,使用一个调用Contains的lambda表达式

代码语言:javascript
复制
// Replace the loop entirely with this
query = query.Where(c => !illegals.Contains(c));
票数 11
EN

Stack Overflow用户

发布于 2018-09-30 07:04:15

这是因为,虽然乍一看,for循环似乎被正确地限制了,但每次迭代都捕获传递给Where的闭包中的索引。闭包最有用的特性之一是,它们通过引用捕获,从而支持各种强大而复杂的技术。但是,在本例中,这意味着在随后的foreach循环中执行查询时。索引已超过数组的长度。

要解决这个问题,最简单的更改是创建一个循环作用域,复制索引循环控制变量的当前值,并在闭包中引用该值,而不是直接引用循环控制变量。

例如:

代码语言:javascript
复制
for (int i = 0; i < illegals.Length; i++)
{
    var index = i;
    query = query.Where(c => c != illegals[index]);
}

然而,正如其他人所指出的那样,有更好的方法来写这篇文章,使问题完全无效,而且他们也有提高抽象水平的优点。

例如,您可以使用System.Linq.Enumerable.Except

代码语言:javascript
复制
var legals = query.Except(illegals);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52575358

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档