Eric Lippert a écrit une excellente série d'articles sur les limites (et les décisions de conception d'influencer les choix) sur itérateur blocs
En particulier itérateur blocs sont mis en œuvre par certains sophistiqué compilateur de code transformations. Ces transformations auraient un impact avec les transformations qui se produisent à l'intérieur des fonctions anonymes ou des lambdas telle que, dans certaines circonstances, ils auraient tous les deux essayer de "convertir" le code dans une autre construction qui était incompatible avec les autres.
En conséquence, ils sont interdits à partir de l'interaction.
Comment itérateur blocs de travail sous le capot est traitée avec bien ici.
Un exemple simple d'une incompatibilité:
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();
}
Le compilateur est à la fois vouloir convertir ce à quelque chose comme:
// 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();
}
et dans le même temps, l'itérateur aspect est d'essayer de faire c'est de travailler pour faire un peu l'état de la machine. Certains exemples simples pourrait fonctionner avec une bonne quantité de vérifications (premier traitant de l' (éventuellement de manière arbitraire nexted fermetures), puis de voir si le très bas niveau des classes obtenues pourraient être transformés en itérateur de l'état des machines.
Mais ce serait
- Beaucoup de travail.
- Ne pouvait pas fonctionner dans tous les cas, sans à tout le moins l'itérateur bloc aspect d'être en mesure d'empêcher la fermeture de l'aspect de l'application de certaines transformations de l'efficacité (comme la promotion des variables locales variables d'instance plutôt que d'une véritable classe de fermeture).
- Si il y avait encore une petite chance de chevauchement où il est impossible ou suffisamment dur pour ne pas être mis en œuvre alors que le nombre de questions de soutien résultant serait susceptible d'être élevé depuis la subtile modification de rupture serait perdu de nombreux utilisateurs.
- Il peut être très facilement contourné.
Dans votre exemple, comme ceci:
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;
}