Saya memiliki kode berikut:
public double CalculateDailyProjectPullForceMax(DateTime date, string start = null, string end = null)
{
Log("Calculating Daily Pull Force Max...");
var pullForceList = start == null
? _pullForce.Where((t, i) => _date[i] == date).ToList() // implicitly captured closure: end, start
: _pullForce.Where(
(t, i) => _date[i] == date && DateTime.Compare(_time[i], DateTime.Parse(start)) > 0 &&
DateTime.Compare(_time[i], DateTime.Parse(end)) < 0).ToList();
_pullForceDailyMax = Math.Round(pullForceList.Max(), 2, MidpointRounding.AwayFromZero);
return _pullForceDailyMax;
}
Sekarang, saya telah menambahkan komentar di jalur yang ReSharper sarankan perubahan. Apa artinya itu, atau mengapa harus diubah?implicitly captured closure: end, start
Jawaban:
Peringatan itu memberi tahu Anda bahwa variabel
end
danstart
tetap hidup karena setiap lambda di dalam metode ini tetap hidup.Lihatlah contoh singkatnya
Saya mendapat peringatan "Penutupan yang ditangkap secara implisit: g" di lambda pertama. Ini memberi tahu saya bahwa
g
tidak bisa dikumpulkan sampah selama lambda pertama digunakan.Kompiler menghasilkan kelas untuk kedua ekspresi lambda dan menempatkan semua variabel di kelas itu yang digunakan dalam ekspresi lambda.
Jadi dalam contoh saya
g
dani
ditahan di kelas yang sama untuk eksekusi delegasi saya. Jikag
benda berat dengan banyak sumber daya tertinggal, pengumpul sampah tidak dapat mengklaimnya kembali, karena referensi di kelas ini masih hidup selama ada ekspresi lambda yang digunakan. Jadi ini potensi kebocoran memori, dan itulah alasan peringatan R #.@plintor Seperti dalam C # metode anonim selalu disimpan dalam satu kelas per metode ada dua cara untuk menghindari ini:
Gunakan metode instance daripada yang anonim.
Pisahkan penciptaan ekspresi lambda menjadi dua metode.
sumber
Random
instance.Setuju dengan Peter Mortensen.
Compiler C # hanya menghasilkan satu jenis yang merangkum semua variabel untuk semua ekspresi lambda dalam suatu metode.
Misalnya, diberi kode sumber:
Kompiler menghasilkan jenis seperti:
Dan
Capture
metode ini dikompilasi sebagai:Meskipun lambda kedua tidak digunakan
x
, itu tidak bisa menjadi sampah yang dikumpulkan karenax
dikompilasi sebagai properti dari kelas yang dihasilkan yang digunakan dalam lambda.sumber
Peringatan ini valid dan ditampilkan dalam metode yang memiliki lebih dari satu lambda , dan mereka menangkap nilai yang berbeda .
Ketika metode yang berisi lambdas dipanggil, objek yang dihasilkan kompiler dipakai dengan:
Sebagai contoh:
Periksa kode yang dihasilkan untuk kelas ini (dirapikan sedikit):
Perhatikan contoh
LambdaHelper
toko yang dibuat baikp1
danp2
.Bayangkan itu:
callable1
menyimpan referensi berumur panjang untuk argumennya,helper.Lambda1
callable2
tidak menyimpan referensi ke argumennya,helper.Lambda2
Dalam situasi ini, referensi
helper.Lambda1
juga secara tidak langsung merujuk string ke dalamp2
, dan ini berarti bahwa pengumpul sampah tidak akan dapat membatalkan alokasi itu. Paling buruk itu adalah kebocoran memori / sumber daya. Selain itu, objek dapat tetap hidup lebih lama dari yang dibutuhkan, yang dapat berdampak pada GC jika dipromosikan dari gen0 ke gen1.sumber
p1
daricallable2
seperti ini:callable2(() => { p2.ToString(); });
- apakah ini masih tidak menyebabkan masalah yang sama (pengumpul sampah tidak akan dapat membatalkan alokasi itu) karenaLambdaHelper
masih mengandungp1
danp2
?LambdaHelper
atas) untuk semua lambdas dalam metode induk. Jadi, bahkan jikacallable2
tidak digunakanp1
, itu akan berbagi objek tangkapan yang samacallable1
, dan objek tangkapan itu akan merujuk keduanyap1
danp2
. Perhatikan bahwa ini hanya penting untuk tipe referensi, danp1
dalam contoh ini adalah tipe nilai.Untuk kueri Linq ke Sql, Anda mungkin mendapatkan peringatan ini. Ruang lingkup lambda mungkin hidup lebih lama dari metode karena fakta bahwa permintaan sering diaktualisasikan setelah metode berada di luar cakupan. Bergantung pada situasi Anda, Anda mungkin ingin mengaktualisasikan hasil (yaitu melalui .ToList ()) dalam metode untuk memungkinkan GC pada vars instance metode yang ditangkap dalam L2S lambda.
sumber
Anda selalu dapat menemukan alasan R # saran hanya dengan mengklik petunjuk seperti yang ditunjukkan di bawah ini:
Petunjuk ini akan mengarahkan Anda ke sini .
sumber