33

「暗黙的にキャプチャされた閉鎖」が何を意味するかは通常知っていますが、今日、次のような状況に遭遇しました。

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
}

他のアクションも暗黙のうちにキャプチャするのはなぜですか? 両方の行のどちらかをコメントしても、もう一方は警告を表示しません。ReSharper が私に警告している危険を知っている人はいますか?

編集:ReSharper 8.0.1

4

3 に答える 3

35

ここでの問題は、変数を閉じると、舞台裏でコンパイラが新しい名前のない型を作成し、そのブロックで閉じられるすべての変数のインスタンス フィールドをその型に与え、すべての匿名のメソッドを与えることです。メソッドをそのコード ブロックで呼び出し、そのオブジェクトの1 つのインスタンスを渡します。

これは、最初のデリゲートの有効期間がそのクロージャー オブジェクトを存続させ、内部的にオブジェクトbに加えてオブジェクトへの参照を持ち、aその逆であることを意味します。

あなたの場合、それは問題でActionはありません。特にメモリを集中的に使用するものではないため、もう少し長く存続させることは実際には問題ではありません。

理論的には、C# チームは、この特定のケースでは、同じブロック内のクロージャごとに新しい名前のない型を作成できることを保証できましたが、一般的なケースを悪化させるため、そうしないことを選択しました。

于 2013-09-17T20:34:16.697 に答える
0

そして警告、私はこれに腹を立てていました:

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;
    }
}

「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;
        }
    }

結構です。

私が発狂した理由は?

scac と customerCode は、どちらもメソッドに渡される文字列です。しかし、customerCode を cc に置き換えても、同じ警告が表示され続けました。

閉鎖は実際には大騒ぎでしたが、Resharper はそれを誤って報告していました。

于 2014-03-12T01:26:27.403 に答える
0

これは前に見たことがあります。ラムダの存続期間中保持される変数に関係しているため、変数が大きいとメモリ不足が発生する可能性があります。

于 2013-09-17T20:33:53.513 に答える