2011-08-26 52 views
4

下面的代碼(用於在LinqPad中運行)旨在將「foo/skip/bar」字符串解析爲項目對象,跳過「skip」位,產生用於「foo」和「bar」的項目對象。運行時,會生成2個「酒吧」項目。.NET IEnumerator <string>當在yield塊中時不會在MoveNext上前進

在TryGetChild方法中,當找到「skip」時,枚舉器從「skip」向前移動到「bar」。但是,當執行返回到調用方法時,枚舉器又回到「跳過」。

我認爲這是一些產量塊怪異,就好像我在Main()中進行拆分並將枚舉器傳遞到Walk()它可以正常工作。有人可以解釋一下統計員如何返回?是否正在創建一個新的?

編輯:這是我在我的代碼中發現的似乎很奇怪的情況的一個非常簡化的版本。我出於好奇問這個問題,而不是尋找我已經找到的解決方法。

/* output from program 

enumerator moved to foo 
enumerator moved to skip 
enumerator moved to bar 
enumerator moved to bar 

Item [] (3 items) 

foo 
bar  
bar 
*/  


static void Main() 
{ 
    Walk("foo/skip/bar").ToArray().Dump(); 
} 

private static IEnumerable<Item> Walk(string pathString) 
{ 
    var enumerator = pathString.Split('/').ToList().GetEnumerator(); 
    var current = new Item() { S = "" }; 
    while (enumerator.MoveNext()) 
    { 
     Console.WriteLine("enumerator moved to " + enumerator.Current); 
     yield return current.TryGetChild(enumerator); 
    } 
} 
class Item 
{ 
    public string S { get; set; } 

    public Item TryGetChild(IEnumerator<string> enumerator) 
    { 
     if (enumerator.Current == "skip") 
     { 
      enumerator.MoveNext(); //iterator moves on to 123 
      Console.WriteLine("enumerator moved to " + enumerator.Current); 
     } 
     return new Item() { S = enumerator.Current }; 
    } 
} 
+1

你的代碼需要使用這種方法的原因是什麼?看起來你的目標可以以更簡單的方式實現。 – dlev

+0

@dlev:看到編輯 – mcintyre321

回答

4

您看到此行爲的原因是List<T>.GetEnumerator()返回List<T>.Enumerator的一個實例,這是一個結構。因此,您正在將值類型傳遞給TryGetChild()方法,並且該類型的任何突變(包括由MoveNext()完成的那些突變)將在調用者中反映出而不是

+0

該死的,我剛剛也得出了這個結論(儘管不是通過查看IL,只是通過做你在最後一句中提出的建議。這是一個相當好的問題... – Chris

+0

@Chris它是,它不是總的來說,這很好,但是依靠傳遞給調查員的問題無論如何都是在尋求麻煩, – dlev

+0

是的,我確實考慮過在我的評論中加入「以及直接從不使用統計員的另一個原因」。它看起來很安全一目瞭然...... :) – Chris

0

我認爲yield僅使用IEnumerableIEnumerable<T>循環時的作品。

+0

它在IEnumerable 循環中也可以工作 – mcintyre321

+0

你能澄清你的意思嗎?「只有作品」......當然,如果他不試圖在單獨的方法中推進迭代器,它肯定會工作正常。 .. – Chris

+0

'yield'絕對不是問題。查看我的答案,瞭解真正發生的事情。 – dlev

相關問題