You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# 9静态Lambda为何仍存在Target属性值?

C# 9静态Lambda的Action.Target不为null的问题及解决办法

问题现象

C# 9引入的static Lambda本应避免捕获外部实例状态,但将其赋值给Action后,检查.Target属性时会发现它并非null——而是指向编译器自动生成的嵌套静态类实例,这和直接指向静态方法的Action行为不一致。

示例代码:

Action action = static () => Console.WriteLine("test");
if(action.Target != null)
{
    // 实际会进入此分支,与预期不符
}

这种情况会破坏你构建的弱引用事件系统逻辑:原本通过.Target == null判断无需处理弱引用,但静态Lambda的.Target会导致该判断失效。

原因分析

编译器处理无捕获的static Lambda时,并未直接将其映射为独立的静态方法,而是生成了一个命名类似<>c的嵌套静态类,在该类中实现Lambda逻辑,并创建该类的静态单例实例。最终Action指向的是这个单例实例的方法,因此.Target会指向该静态类实例,而非null。

而直接引用静态方法时,Action的.Method本身是静态方法,.Target自然为null。

解决办法

方案1:修正判断逻辑

结合.Method.IsStatic和.Target的类型特征来判断:

  • 如果委托指向的方法是静态的,即使.Target不为null,也不会持有外部业务实例的引用(编译器生成的静态类实例不会造成内存泄漏)
  • 额外判断.Target是否为编译器生成的闭包类(通过类型名称包含<>c标记识别)

修改后的判断代码:

Action action = static () => Console.WriteLine("test");
bool requiresWeakReference = !(action.Method.IsStatic || 
    (action.Target != null && 
     action.Target.GetType().Name.Contains("<>c") && 
     action.Method.IsStatic));

if (requiresWeakReference)
{
    // 对外部实例使用弱引用处理
}

方案2:直接使用静态方法替代Lambda

如果场景允许,直接将静态方法赋值给Action,此时.Target会保持为null,符合最初的判断逻辑:

static void TestAction() => Console.WriteLine("test");
Action action = TestAction;
// 此时action.Target == null,判断逻辑正常生效

内容的提问来源于stack exchange,提问作者trampster

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 04:53:12