Cobalah untuk mengkompilasi kode berikut dan Anda akan menemukan bahwa kompiler membutuhkan> 3 GB RAM (semua memori gratis di mesin saya) dan waktu yang sangat lama untuk mengkompilasi (sebenarnya saya mendapatkan pengecualian IO setelah 10 menit).
using System;
using System.Linq;
public class Test
{
public static void Main()
{
Enumerable.Range(0, 1).Sum(a =>
Enumerable.Range(0, 1).Sum(b =>
Enumerable.Range(0, 1).Sum(c =>
Enumerable.Range(0, 1).Sum(d =>
Enumerable.Range(0, 1).Sum(e =>
Enumerable.Range(0, 1).Sum(f =>
Enumerable.Range(0, 1).Count(g => true)))))));
}
}
Adakah yang bisa menjelaskan perilaku penasaran ini?
Versi CS: Microsoft (R) Visual C # Compiler versi 4.0.30319.17929 Nama OS: Microsoft Windows 7 Ultimate Versi OS: 6.1.7601 Paket Layanan 1 Build 7601
Jawaban:
Saya percaya bahwa ini terkait dengan inferensi tipe dan / atau generasi lambda (ketika inferensi tipe harus berlawanan arah dengan normal), dikombinasikan dengan resolusi yang berlebihan. Sayangnya, hanya menyediakan parameter tipe tidak membantu situasi (di mana mungkin masih harus melakukan pemeriksaan tipe).
Kode berikut, yang secara logis harus merupakan kode yang setara dari Anda, setelah lambda dianalisis, dikompilasi tanpa masalah:
Saya percaya Eric Lippert telah memposting sebelumnya bahwa inferensi tipe adalah salah satu tempat di kompiler C # di mana (masalah tertentu) dapat memaksa kompiler untuk mencoba memecahkan masalah NP-Complete dan satu-satunya strategi nyata (seperti di sini) adalah kekerasan. Jika saya dapat menemukan referensi yang relevan, saya akan menambahkannya di sini.
Referensi terbaik yang dapat saya temukan adalah di sini di mana Eric membahas fakta bahwa itu adalah pekerjaan resolusi kelebihan beban yang menyebabkan biaya sebenarnya - ingat, Enumerable.Sum memiliki 10 kelebihan beban yang menerima lambda / metode.
sumber
10^n
kombinasi (di manan
jumlah metode yang dirantai). Kedengarannya masuk akal (sebagai penjelasannya).that^numberofpossibletypes