2014-05-07 65 views
0

我使用HtmlAgilityPack解析HTML頁面並從選擇列表中檢索若干選項元素。IEnumerable在沒有實際調用的情況下過濾發生的地方

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

新價值的標準任何人都可以解釋這種反常現象?我有望使一個調用聯合新查詢結果的原始結果,但它似乎是自動發生的,雖然結果是我的願望,但我無法解釋它發生的方式(或者它會繼續的確定性)這樣的行爲)

+1

你是LINQ延遲評估的受害者嗎?看看[這個問題](http://stackoverflow.com/questions/11352244/c-sharp-linq-delayed-execution) – Travis

+0

看來,我是......我從來沒有真正以這種方式做過任何事情我正在改變比較變量的值。 –

回答

6

LINQ查詢使用延遲執行,這意味着只要您列舉結果他們跑。

當您更改查詢中正在使用的變量時,您實際上正在更改下一次查詢運行的結果,這是您下次迭代結果的時間。

瞭解更多關於這個herehere

這實際上是通過設計,而且在許多情況下,它是非常有用的,而且有時是必要的。但是,如果您需要立即進行評估,則可以在查詢結束時調用ToList()方法,您可以查詢哪個,併爲您提供正常的List<T>對象。

1

divisions變量包含一個未處理的枚舉器,它在節點列表中的每個元素上調用代碼x.Text.Contains(string.Format("{0} {1}", ageGroup, gender))。由於在處理該枚舉器之前更改了ageGroup,因此它將使用該新值而不是舊值。

例如,下面的代碼輸出一行文本「梨」:

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); 
} 
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>(); 
相關問題