24

ラムダ式を使用すると、通常のforeachループとは対照的にGCのガベージが生成されますか?

// Lambda version
Foos.ForEach(f=>f.Update(gameTime));

// Normal approach:
foreach (Foo f in Foos)
{
  f.Update(gameTime);
}

CLRプロファイラーは、私が69.9%のsystem.Action <T>を持っていることを示しており、上記のforeachループのランババージョンであると思われます。本当?

編集:Microsoft CLRプロファイラーを使用しました:http://download.microsoft.com/download/4/4/2/442d67c7-a1c1-4884-9715-803a7b485b82/clr%20profiler.exe またはhttp://msdn.microsoft .com / en-us / library / ff650691.aspx

4

2 に答える 2

24

はい、クロージャがローカルスコープから変数をキャプチャする場合(つまりgameTime、このコンテキストでは)、ラムダはガベージを作成します。

たとえば、次のC#関数:

static void TestLambda(List<Foo> Foos, DateTime gameTime)
{
    Foos.ForEach(f => f.Update(gameTime));
}

これに翻訳されます:

private static void TestLambda(List<Foo> Foos, DateTime gameTime)
{
    Program.<>c__DisplayClass1 <>c__DisplayClass = new Program.<>c__DisplayClass1();
    <>c__DisplayClass.gameTime = gameTime;
    Foos.ForEach(new Action<Foo>(<>c__DisplayClass.<TestLambda>b__0));
}

結果のコードには2つのインスタンスがあることに注意してください。つまり、割り当てられているオブジェクト(クロージャ)だけでなく、キャプチャされた変数を保持するオブジェクト(変数レコードのエスケープ)もあります。newAction

于 2011-08-20T16:23:07.300 に答える
0

この場合、新しい型を生成するジェネリックメソッド(ForEach)を使用していると思います(Fooが参照型であると仮定すると、新しい型は1つだけ生成されます)、ラムダは通常の匿名メソッドとしてコンパイルされます。それについては、メモリ使用量が直線的に増加することを示唆するものはありません。

プロファイラーに関する限り、メモリやGCについては何も測定していません。メソッドの実行に費やされた時間を測定しているので、ラムダは「通常の」方法よりも大幅に遅くならないようにする必要があります。

于 2011-08-20T16:22:11.060 に答える