SORU
13 AĞUSTOS 2015, PERŞEMBE


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
13 AĞUSTOS 2015, PERŞEMBE


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 keser
  • return 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 eski items oldu tekrarlanır, bu yüzden sonunda bir düz bellek List<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.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Ben Vivona

    Ben Vivona

    24 Ocak 2010
  • echifitness

    echifitness

    9 Kasım 2008
  • Jonnyriddlin1

    Jonnyriddlin

    4 Ocak 2007