Neden bu yöntem sonsuz bir döngüye neden?
İş arkadaşlarımdan biri, sonsuz bir döngüye neden olan bu yöntem hakkında bir soru ile bana geldi. Gerçek kod biraz burada yazılan ilgili değildir, ama aslında sorun bu aşağı kaynar:
private IEnumerable<int> GoNuts(IEnumerable<int> items)
{
items = items.Select(item => items.First(i => i == item));
return items;
}
Bugerekir(düşünür) çok verimsiz bir şekilde bir listenin bir kopyasını oluşturmak için. Onu aradım:
var foo = GoNuts(new[]{1,2,3,4,5,6});
Sonuç sonsuz bir döngü. Garip.
Parametre değiştirme kodu biraz değiştirdim, üslup kötü bir şey olduğunu düşünüyorum
var foo = items.Select(item => items.First(i => i == item));
return foo;
Bu işe yaradı. Yani, program tamamlandı; bir istisna.
Daha fazla deney bu işleri de gösterdi:
items = items.Select(item => items.First(i => i == item)).ToList();
return items;
Kadar basit
return items.Select(item => .....);
Meraklı.
Sorun olursa değerlendirme o ifadesinden ertelenmiş ise tek parametre Yeniden Atama ile, ama yapmak zorunda olduğu açıktır. Eğer ToList()
eklersem çalışır.
Yanlış ne genel, belirsiz bir fikrim yok. Select
kendi çıkış yineleme sona erdi gibi görünüyor. Bu genellikle IEnumerable
bir koleksiyonu yineleme değişirse atar çünkü biraz başlı başına tuhaf.
Anlamadığım şey, bu işin nasıl yürüdüğünü iç ile haşır neşir olmadığım için, Yeniden Atama parametresi bu sonsuz bir döngüye neden olur.
Sonsuz döngü oluşuyor burada açıklamak isteyen iç daha fazla bilgisi olan biri var mı?
CEVAP
Bu cevap anahtarıertelenmiş yürütme. Bunu yaptığınızda
items = items.Select(item => items.First(i => i == item));
yaparsındeğilitems
dizi yönteme geçti yineleme. Bunun yerine, yeni bir atama kendisini geri başvurular, yalnızca arayanın sonuçları numaralandırma başlar yineleme başlar IEnumerable<int>
,.
Tüm diğer düzeltmeler sorunu ele alınmasının nedeni budur: tek yapman gereken IEnumerable<int>
kendisi için geri besleme durdurmak için
var foo
kullanarak farklı bir değişken kullanarak kendi referans keserreturn items.Select...
kullanarak tüm ara değişkenleri kullanarak, kendi kendine referans keser- Kullanarak
ToList()
sonlarını kendi kendine referansla kaçınarak ertelenmiş yürütme:items
yeniden atanır eskiitems
oldu tekrarlanır, bu yüzden sonunda bir düz bellekList<int>
.
Ama eğer kendini besliyor. nasıl bir şey hiç olmayacak mı?
Bu doğru bir şey değil! Şu an deneyin yineleme items
bunu sormak için ilk madde, ertelenmiş ister sıra sıra fed için ilk parça için işlem anlamına gelir sırası soran kendisi ilk parça için işlem. Bu noktada, sırası işlem için ilk öğeyi döndürmek için ilk önce maddenin kendisi işlemek için almak gerekir, çünkü turtles all the way down.
Neden bu sonsuz bir döngüye girer ki?...
Neden GCC ile x 86 tamsayı taşması son...
Hayır genişlik/yükseklik maddeleri aya...
Neden önemli GetHashCode yöntem geçers...
Neden Java temel yöntem statik mi?...