コードインスペクション: ラムダ式 / 匿名メソッドは含まれているコンテキストをキャプチャしてはいけません
C# のラムダ式は、通常、パフォーマンスとメモリへの影響に関連しています。 ラムダ式が提供する抽象化は、ほとんどのシナリオで追加コストの価値がありますが、これらのコストは一部のホットパスコードでは受け入れられない場合があります。
このようなコードを区別するために、 [RequireStaticDelegate] 属性を JetBrains.Annotations から使用できます。 この属性は、この属性でアノテーションが付けられたパラメーターに渡されるラムダ式に含まれるコンテキストのキャプチャーをレポートすることにより、割り当てのないコーディング手法を適用します。 含まれているコンテキストをキャプチャーしないラムダ式は、デリゲートインスタンスを一度だけ割り当て、残りのプログラム実行のためにキャッシュするため、このようなラムダ式は割り当てがなくなります。
これは、ユーザーが Func デリゲート型入力パラメーターを使用してキャッシュされた値を計算することを期待する API の例です。
class Cache
{
private Dictionary<string, int> _cache = new();
public int GetData(string key,
[RequireStaticDelegate] Func<string, int> calculator)
{
if (!_cache.TryGetValue(key, out var value))
{
value = _cache[key] = calculator(key);
}
return value;
}
}
... しかし、間違いを犯して、 x パラメーターの代わりに変数 key をキャプチャーするのは簡単すぎます。
class CacheTest
{
public CacheTest()
{
var cache = new Cache();
var key = "abc";
// Warning: anonymous function
// should not have captures of the containing context
var a = cache.GetData(key, calculator: x => key.Length);
}
}
JetBrains Rider はそのようなキャプチャを報告しますが、 クイックフィックスは提案しません。呼び出しコンテキストから何もキャプチャしない状態でコードが正常に動作することを確認してください。
デリゲートパラメーターとしてメソッドを渡す場合、JetBrains Rider は、コンパイラー レベルでのキャプチャーを防ぐため、可能な場合はラムダ式に static 修飾子を追加することを提案します:
// Allocates on each call
var a = cache.GetData(key, calculator: Compute);
// Doesn't allocate
var b = cache.GetData(key, calculator: static x => Compute(x));
2026 年 6 月 12 日