我使用HtmlAgilityPack来解析HTML页面并从选择列表中检索许多选项元素。
GvsaDivisions
是一个从POST结果中返回原始html的方法,在问题的上下文中是不敬的
public IEnumerable<SelectListItem> Divisions(string season, string gender, string ageGroup)
{
var document = new HtmlDocument();
var html = GvsaDivisions(season);
document.LoadHtml(html);
var options = document.DocumentNode.SelectNodes("//select//option").Select(x => new SelectListItem() { Value = x.GetAttributeValue("value", ""), Text = x.NextSibling.InnerText });
var divisions = options.Where(x => x.Text.Contains(string.Format("{0} {1}", ageGroup, gender)));
if (ageGroup == "U15/U16")
{
ageGroup = "U15/16";
}
if (ageGroup == "U17/U19")
{
ageGroup = "U17/19";
}
return divisions;
}
我观察到的是......一旦options.Where()
被执行,分区就会包含一个结果。在ageGroup == "U15/U16"
的测试和ageGroup = "U15/16"
的分配之后,分区现在包含3个结果(原始1,添加2个新匹配ageGroup
新值的标准
有人可以解释这个异常吗?我希望将一个新的Where查询的结果调用到Union的原始结果,但它似乎是自动发生的。虽然结果是我想要的,但我无法解释它是如何发生的(或确定它会继续以这种方式行事)
答案 0 :(得分:6)
LINQ查询使用延迟执行,这意味着只要枚举结果就会运行它们。
当您更改查询中使用的变量时,实际上您正在更改下次运行查询的结果,这是您下次迭代结果时的结果。
这实际上是按设计进行的,在许多情况下它非常有用,有时也是必要的。但是,如果您需要立即进行评估,可以在查询结束时调用ToList()
方法,具体化您查询并为您提供正常的List<T>
对象。
答案 1 :(得分:1)
divisions
变量包含一个未处理的枚举器,它在节点列表中的每个元素上调用代码x.Text.Contains(string.Format("{0} {1}", ageGroup, gender))
。由于在处理该枚举数之前更改了ageGroup,因此它使用该新值而不是旧值。
例如,以下代码输出一行文本&#34; pear&#34;:
List<string> strings = new List<string> { "apple", "orange", "pear", "watermelon" };
string matchString = "orange";
var queryOne = strings.Where(x => x == matchString);
matchString = "pear";
foreach (var item in queryOne)
{
Console.WriteLine(" " + item);
}
答案 2 :(得分:0)
我正在思考与特拉维斯相同的问题,延迟执行linq。
我不确定这是否可以避免这个问题,但我通常会将结果放入这样的直接收集中。根据我的经验,一旦你把结果推到一个真正定义的集合中,我相信它可能不会延迟执行。
List<SelectListItem> options = document.DocumentNode.SelectNodes("//select//option").Select(x => new SelectListItem() { Value = x.GetAttributeValue("value", ""), Text = x.NextSibling.InnerText }).Where(x => x.Text.Contains(string.Format("{0} {1}", ageGroup, gender))).ToList<SelectListItem>();