假设我有三个对象:“ a”,“ b”和“ c”。对象“ a”和“ c”是长期存在的,静态引用的服务单例。对象“ b”是短暂的,即没有静态引用可使它保持活动状态。
现在假设对象“ a”在其方法之一的范围内创建了对象“ b”的实例,例如
B b = new B();
进一步假设类B看起来像这样:
public B ()
{
C.ActionList.Add ( SomeMethod );
}
void SomeMethod ()
{
...
}
现在,对象“ b”生存了多长时间?我的推测是,它超出了称为构造函数的方法的范围。具体来说,只要其方法仍在对象'c'的'ActionList'中即可。
那是对的吗?如果没有,它将被垃圾回收,当'c'运行其'ActionList'中的所有方法时会发生什么?
额外的问题:如果'b'上的方法不是命名的,而是匿名的,并在构造函数中编写如下,该怎么办:
public B ()
{
C.ActionList.Add ( () => {
...
} );
}
具体来说,只要其方法仍在对象'c'的'ActionList'中即可。
对,那是正确的。实例方法的委托会为实例本身创建“硬引用”,并将其保持活动状态。您的第二个问题无关紧要。
请注意,这就是事件订阅是.NET中常见的“内存泄漏”来源的原因-从技术上讲,它们不是泄漏,但是事件订阅基于委托,并且具有相同的行为,因此事件订阅持有对实例。
如果'b'上的方法不是命名的,而是匿名的,并且在构造函数中以lambda编写,该怎么办?
都一样 如果lambda使用所讨论实例的状态,则它将被编译器转换为具有对该实例的引用的类型的实例方法,并保留一个引用。(请注意,如果某些lambda表达式不依赖于任何封闭的值,实例等,则有可能将其转换为静态方法,在这种情况下,该lambda表达式将不包含引用。)
在您的情况下,的内容...
将确定这一点。如果您的表达式不过是:: () => { Console.WriteLine("Foo"); }
,则它不需要关闭实例中的任何值,也不需要使用有问题的实例,因此它不会保存引用。() => { Console.WriteLine(this.Foo); }
但是,如果这样做,它将在类型上创建对的引用的方法this
,并使类实例保持活动状态。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句