ner*_*hon 5 c# delegates scope action object-lifetime
假设我有三个对象:'a','b'和'c'.对象'a'和'c'是长寿的,静态引用的服务单例.对象'b'是短暂的,即没有静态引用使其保持活动状态.
现在假设对象'a'在其一个方法的范围内创建对象'b'的实例,例如
B b = new B();
Run Code Online (Sandbox Code Playgroud)
进一步假设B类看起来像这样:
public B ()
{
C.ActionList.Add ( SomeMethod );
}
void SomeMethod ()
{
...
}
Run Code Online (Sandbox Code Playgroud)
现在,对象'b'存活了多长时间?我的推测是,它超出了称为构造函数的方法的范围; 具体来说,只要它的方法仍然在对象'c'的'ActionList'中.
那是对的吗?如果没有,它会被垃圾收集,当'c'运行'ActionList'中的所有方法时会发生什么?
额外的问题:如果'b'上的方法没有被命名,但匿名并在构造函数中写入如下,该怎么办?
public B ()
{
C.ActionList.Add ( () => {
...
} );
}
Run Code Online (Sandbox Code Playgroud)
具体来说,只要它的方法仍然在对象'c'的'ActionList'中.
对,那是正确的.实例方法的委托为实例本身创建"硬引用",并使其保持活动状态.你的第二个问题不相关.
请注意,这就是为什么事件订阅是.NET中"内存泄漏"的常见原因 - 它们在技术上不会泄漏,但事件订阅基于委托,并且具有相同的行为,因此事件订阅包含对实例.
如果'b'上的方法没有命名,但匿名并在构造函数中写入lambda会怎样?
这是一样的.如果lambda使用有问题的实例的状态,它将变为一个类型的实例方法,该类型具有编译器对该实例的引用,并保持引用.(请注意,如果某些lambda表达式不依赖于任何已关闭的值,实例等,则可能会将某些lambda表达式转换为静态方法,在这种情况下,它不会保留引用.)
在你的情况下,...将确定这个内容.如果你的表达式只是:() => { Console.WriteLine("Foo"); },它不需要关闭实例中的任何值,也不会使用有问题的实例,因此它不会保留引用.() => { Console.WriteLine(this.Foo); }但是,如果这样做,它将在具有引用的类型上创建方法this,并使类实例保持活动状态.
| 归档时间: |
|
| 查看次数: |
605 次 |
| 最近记录: |