Eric Lippert, yineleyici bloklar üzerindeki sınırlamalar (ve bu seçimleri etkileyen tasarım kararları) üzerine mükemmel bir makale dizisi yazmıştır.
Özellikle yineleyici bloklar, bazı karmaşık derleyici kod dönüşümleri tarafından uygulanır. Bu dönüşümler, anonim işlevler veya lambdalar içinde meydana gelen dönüşümleri etkileyecek, öyle ki belirli durumlarda her ikisi de kodu diğeriyle uyumsuz olan başka bir yapıya 'dönüştürmeye' çalışacaklardı.
Sonuç olarak, etkileşimden men edilirler.
Yineleme bloklarının başlık altında nasıl çalıştığı burada iyi ele alınmaktadır .
Uyumsuzluğun basit bir örneği olarak:
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;
}
return items.ToList();
}
Derleyici aynı anda bunu aşağıdaki gibi bir şeye dönüştürmek istiyor:
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();
}
ve aynı zamanda yineleyici yönü, küçük bir durum makinesi yapmak için işini yapmaya çalışıyor. Bazı basit örnekler, makul miktarda akıl sağlığı kontrolü ile işe yarayabilir (ilk önce (muhtemelen keyfi olarak) iç içe geçmiş kapanışlarla ilgilenir), sonra ortaya çıkan en alt düzey sınıfların yineleyici durum makinelerine dönüştürülüp dönüştürülemeyeceğini görmek.
Ancak bu
- Oldukça fazla iş.
- En azından yineleyici blok yönü, kapanış yönünün verimlilik için belirli dönüşümleri uygulamasını engelleyebilmesi (tam teşekküllü bir kapanış sınıfı yerine yerel değişkenleri örnek değişkenlerine yükseltmek gibi) olmadan tüm durumlarda muhtemelen çalışamaz.
- Uygulanmasının imkansız olduğu veya yeterince zor olduğu yerlerde küçük bir çakışma şansı bile olsaydı, ortaya çıkan destek sorunlarının sayısı büyük olasılıkla yüksek olurdu çünkü ince kırılma değişikliği birçok kullanıcı için kaybedilirdi.
- Etrafında çok kolay bir şekilde çalışılabilir.
Örneğinizde şöyle:
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
5.0'daawait
içeriye izin veren anonim lambdalara sahip olabildiğimize göre, neden halayield
içeride anonim yineleyiciler uygulamadıklarını bilmek isterim . Aşağı yukarı aynı durum makinesi üreteci.