Dan*_*elD 0 c# ienumerable search loops
我知道有很多方法可以对这只猫进行修饰,但是我遇到了一些基本的while循环问题,它们正常退出,但是在从父函数返回IEnumerable.ToList()时会返回(并增加计数器).基本上我要做的是搜索单个关键字的列表并过滤掉结果集,直到我只获得包含所有关键字的项目.
它退出循环,然后一旦命中返回,它就会返回到循环中,i变量增加另一个位置(高于count变量),因此broken [i]抛出一个极限之外的错误.
虽然我知道有更好的方法来执行搜索,但我也非常感兴趣为什么代码会返回到退出的循环,再次递增,并导致错误 - 以及如何修复它.这很奇怪,我以前从未见过这个.是因为.ToList强制枚举备份链吗?
码:
public IEnumerable<Item> GetItemsForSearch(string search=null)
{
ParserDataContext data = new ParserDataContext();
if (search != null && search != "")
{
string[] broken = search.Split(' ');
IEnumerable<Item> watches = data.Items.Where(x => x.Title.ToLower().Contains(broken[0].ToLower())).OrderByDescending(x => x.DateListed).ThenByDescending(x => x.ID);
int i = 1;
int count = broken.Count();
while (i < count)
{
if (broken[i] != null)
item = items.Where(x => x.Title.ToLower().Contains(broken[i].ToLower()));
i++;
}
return items.Take(50).ToList();
}
Run Code Online (Sandbox Code Playgroud)
}
虽然我知道有更好的方法来执行搜索,但我也非常感兴趣为什么代码会返回到退出的循环,再次递增,并导致错误
第一件事是要了解实际发生的事情:代码不会回到已经退出的循环中,它只是i在错误的时间点使用变量的值,即在它增加之后.这是一个已知的功能:编译器捕获i的broken[i]直接,未做它的拷贝.
显然,这个功能已经足够烦人,微软可以在C#5.0中宣布修复这个错误的常见情况(特别是在foreach循环中关闭循环变量).
以及如何解决它.
对于C#4.5的用户,一个简单的解决方法是声明一个临时变量而不是使用i.编译器将捕获临时值,使行为符合您的预期:
while (i < count) {
if (broken[i] != null) {
var tmp = broken[i].ToLower();
items = items.Where(x => x.Title.ToLower().Contains(tmp));
}
i++;
}
}
Run Code Online (Sandbox Code Playgroud)
更好的方法是将所有破碎的单词收集在一起,然后在单个镜头中运行选择,如下所示:
var allBroken = broken.Where(b => b != null).Select(ToLower).ToList();
var items = items
.Select(item => new {Item = item, Title = item.Title.ToLower()})
.Where(pair => allBroken.Any(broken => pair.Title.Contains(broken)))
.ToList();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
114 次 |
| 最近记录: |