Pertanyaan Penutup secara tersirat, peringatan ReSharper


Saya biasanya tahu apa arti "penutupan yang tersirat secara implisit", namun, hari ini saya menemukan situasi berikut:

public static void Foo (Bar bar, Action<int> a, Action<int> b, int c)
{
    bar.RegisterHandler(x => a(c)); // Implicitly captured closure: b
    bar.RegisterHandler(x => b(c)); // Implicitly captured closure: a
}

Mengapa saya secara implisit mengambil tindakan lain juga? Jika saya berkomentar salah satu dari kedua baris, yang lain tidak memberi saya peringatan. Ada yang tahu bahaya apa yang ReSharper peringatkan saya?

Edit: ReSharper 8.0.1


32
2017-09-17 20:27


asal


Jawaban:


Masalahnya di sini adalah bahwa ketika Anda menutup variabel apa yang terjadi di belakang layar adalah bahwa compiler menciptakan jenis yang tidak disebutkan namanya baru, memberikan jenis itu sebuah bidang contoh untuk setiap variabel yang ditutup di blok itu, memberikannya metode untuk setiap metode anonim di blok kode itu dan kemudian melewati a satu contoh dari objek itu.

Ini berarti bahwa masa hidup dari delegasi pertama adalah menjaga agar objek penutupan tetap hidup, dan itu memiliki referensi ke objek b, sebagai tambahannya a, secara internal, dan sebaliknya.

Sekarang dalam kasus Anda, itu bukan masalah, sebagai Action bukan sesuatu yang sangat membutuhkan memori, jadi menjaganya agar tetap hidup sedikit lebih lama bukanlah masalah.

Tim C # dapat, secara teori, telah memastikan bahwa dalam kasus khusus ini tipe baru yang tidak disebutkan namanya dapat dibuat untuk setiap penutupan dalam blok yang sama, tetapi mereka memilih untuk tidak membuat kasus umum menjadi lebih buruk.


35
2017-09-17 20:34



Saya pernah melihat ini sebelumnya; itu ada hubungannya dengan variabel yang dipegang untuk seumur hidup lambda, jadi jika mereka besar itu dapat menciptakan tekanan memori.


0
2017-09-17 20:33



Dan peringatan, saya akan marah karena ini:

List<List<string>> allowed = AllowedSCACSwaps;
foreach (List<string> c in allowed.Where(c => c.Contains(scac)))
{
    csc = openCycles.FirstOrDefault(icsc => (icsc.CustomerCode == customerCode) && c.Contains(icsc.SCAC));
    if (null != csc)
    {
        return csc;
    }
}

mengatakan "penutupan implisit untuk customerCode"

string cc = customerCode.ToUpperInvariant();
string sc = scac.ToUpperInvariant();    List<List<string>> allowed = AllowedSCACSwaps;
    foreach (List<string> c in allowed.Where(c => c.Contains(sc)))
    {
        csc = openCycles.FirstOrDefault(icsc => (icsc.CustomerCode == cc) && c.Contains(icsc.SCAC));
        if (null != csc)
        {
            return csc;
        }
    }

Baik-baik saja.

Alasan saya akan gila?

scac dan customerCode keduanya string yang dilewatkan ke dalam metode. Tetapi bahkan ketika saya mengganti customerCode dengan cc, saya terus mendapatkan peringatan yang sama.

Penutupan sebenarnya melebihi scac tetapi Resharper salah melaporkannya.


0
2018-03-12 01:26