C#中Func/Action委托在源对象脱离作用域后是否会变为null?
当源对象失去引用时,Func和Action委托是否会变为null?
问题场景
首先给出涉及的类定义:
类A中定义如下实例方法:
public int CubeAnInt32(int n) { return n * n * n; }
类B中定义如下接收委托参数的方法:
public void CubeAnInt32WithDelegate(int k, Func<int, int> delg) { return delg(k); }
全局作用域相关代码定义如下:
/// 注意:该变量定义在SomeArbitraryCallback()方法作用域外 Func<int, int> cube = default; public void SomeArbitraryCallback() { var refWithinScope = new ClassA(); cube = refWithinScope.CubeAnInt32; return; } public void AnotherCallbackPerformedAfter() { var cubeDependent = new ClassB(); /// 此处是否会因为'cube'抛出NullReferenceException? /// 赋值给'cube'的委托是否已被取消引用? var result = cubeDependent.CubeAnInt32WithDelegate(0, cube); return result; }
核心疑问:当委托绑定的对象脱离作用域(如本例中cube委托绑定的ClassA实例refWithinScope)时,委托是否会被取消引用变为null?还是说委托会持有绑定对象的引用,阻止该对象被GC回收?
解答
结论:示例中的cube委托不会变为null,调用时不会抛出NullReferenceException,委托会持有绑定实例方法的目标对象的强引用,阻止该对象被GC回收。
具体规则如下:
- 当将实例方法赋值给
Func/Action这类委托时,委托内部会同时存储两部分信息:待调用方法的元数据、调用方法时作为this传入的目标实例引用。 - 示例中
cube是方法作用域外的长生命周期变量,SomeArbitraryCallback()执行结束后,虽然局部变量refWithinScope超出作用域失效,但cube内部存储的ClassA实例引用依然是有效强引用。GC会将该ClassA实例判定为可达对象,不会回收它,委托本身也不存在自动被置为null的机制。 - 只有当
cube本身被手动赋值为null,且没有其他任何变量持有该委托、同时目标ClassA实例也没有其他可达引用时,对应的ClassA实例才会被GC回收。 - 补充说明:如果赋值给委托的是静态方法,委托不需要存储实例引用,自然不存在持有对象、阻止GC的逻辑。
内容的提问来源于stack exchange,提问作者user18908005
相关产品推荐
相关产品推荐

