埃裏克利珀對iterator blocks
特別是迭代器塊寫了一個極好的一系列關於限制(和設計決策影響者的選擇)的文章通過一些複雜的編譯器代碼轉換中實現。這些轉變將與匿名函數或lambda表達式,從而在某些情況下,他們將都試圖「轉換」的代碼轉換成一些其他的結構,它是與其他不兼容其內部發生的變革影響。
因此,他們被禁止互動。
迭代塊引擎蓋下是如何工作的是處理好here。
由於不兼容的一個簡單的例子:
public IList<T> GreaterThan<T>(T t)
{
IList<T> list = GetList<T>();
var items =() => {
foreach (var item in list)
if (fun.Invoke(item))
yield return item; // This is not allowed by C#
}
return items.ToList();
}
編譯器同時希望將其轉換爲類似:
// inner class
private class Magic
{
private T t;
private IList<T> list;
private Magic(List<T> list, T t) { this.list = list; this.t = t;}
public IEnumerable<T> DoIt()
{
var items =() => {
foreach (var item in list)
if (fun.Invoke(item))
yield return item;
}
}
}
public IList<T> GreaterThan<T>(T t)
{
var magic = new Magic(GetList<T>(), t)
var items = magic.DoIt();
return items.ToList();
}
,並在同一時間迭代器方面努力做這是製作一個小型狀態機的工作。某些簡單的例子可能具備相當健全檢查(先處理(可能是任意nexted閉包),然後看的工作,如果造成階級最底層水平有可能轉化爲迭代器狀態機。
但是這將是
- 相當多的工作。
- 如果沒有至少迭代器塊方面能夠阻止閉包方面爲效率應用某些轉換(如將局部變量提升爲實例變量而不是完全成熟的閉包類),那麼在所有情況下都可能無法工作。
- 如果甚至有輕微的重疊機會,如果不可能實現或很難實現,那麼支持問題的數量可能會很高,因爲許多用戶會失去微妙的重大改變。
- 它可以很容易解決。
在你的榜樣,像這樣:
public IList<T> Find<T>(Expression<Func<T, bool>> expression)
where T : class, new()
{
return FindInner(expression).ToList();
}
private IEnumerable<T> FindInner<T>(Expression<Func<T, bool>> expression)
where T : class, new()
{
IList<T> list = GetList<T>();
var fun = expression.Compile();
foreach (var item in list)
if (fun.Invoke(item))
yield return item;
}
,我們可以有匿名`async` lambda表達式允許`await`內部在C#5.0中,我很想知道爲什麼他們仍然避風港在裏面實現了帶有yield的匿名迭代器。或多或少,它是一樣的狀態機生成器。 – Noseratio 2014-03-13 09:26:22