ReSharper 2025.2 Help

代码检查:Lambda 表达式/匿名方法不得捕获包含上下文

C# 中的 Lambda 表达式通常会对性能和内存产生一定影响。 尽管 Lambda 表达式提供的抽象在大多数情况下值得额外的开销,但对于某些关键路径代码,这些开销可能是不可接受的。

为了区分此类代码,您可以使用来自 JetBrains.Annotations[RequireStaticDelegate] 属性。 此属性通过报告传递给带有此属性注释的参数的 Lambda 表达式中包含上下文的捕获,强制执行无分配的编码实践。 没有任何包含上下文捕获的 Lambda 表达式仅分配一次委托实例,并在程序执行的其余部分缓存它,因此此类 Lambda 表达式成为无分配的。

以下是一个 API 示例,期望用户使用 Func 委托类型输入参数计算缓存值。

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

……但很容易出错,捕获变量 key 而不是 x 参数:

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

ReSharper 将报告此类捕获,但不会建议任何 快速修复——您需要确保代码在不捕获任何调用上下文的情况下正常工作。

如果您将方法作为委托参数传递,ReSharper 将建议在可能的情况下为 Lambda 表达式添加 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));
最后修改日期: 2025年 9月 27日