does passing a method of one object to another object keep the first object alive?

心已入冬 提交于 2019-12-07 06:27:12

问题


Suppose I have three objects: 'a', 'b' and 'c'. Object 'a' and 'c' are long-lived, statically referenced service singletons. Object 'b' is short-lived, i.e. no static references keep it alive.

Now suppose object 'a' creates an instance of object 'b' in the scope of one of its methods, e.g.

B b = new B();

Further suppose that the class B looks something like this:

public B ()
{
    C.ActionList.Add ( SomeMethod );
}

void SomeMethod ()
{
...
}

Now, how long does object 'b' live? My presumption is that it lives beyond the scope of the method that called its constructor; specifically, for as long as its method is still in the 'ActionList' of object 'c'.

Is that correct? If not, and it gets garbage collected, what happens when 'c' runs all the methods in its 'ActionList'?

Bonus question: What if the method on 'b' is not named, but anonymous and written in the constructor as follows:

public B ()
{
    C.ActionList.Add ( () => {
    ...
    } );
}

回答1:


specifically, for as long as its method is still in the 'ActionList' of object 'c'.

Yes, that is correct. A delegate to an instance method creates a "hard reference" to the instance itself, and will keep it alive. Your second question is not relevant.

Note that this is why event subscriptions are a common source of "memory leaks" in .NET - they don't technically leak, but event subscriptions are based on delegates, and have this same behavior, so an event subscription holds a reference to the instance.

What if the method on 'b' is not named, but anonymous and written in a lambda in the constructor?

This is the same. If the lambda uses state of the instance in question, it will get turned into an instance method on a type with a reference to that instance by the compiler, and hold a reference. (Note that it's possible for some lambda expressions to be turned into static methods, if they don't rely on any closed over values, the instance, etc, in which case it would not hold a reference.)

In your case, the contents of the ... would determine this. If your expression was nothing but: () => { Console.WriteLine("Foo"); }, it wouldn't need to close over any values in the instance, and wouldn't use the instance in question, so it would not hold a reference. If you do () => { Console.WriteLine(this.Foo); }, however, it would create a method on a type with a reference to this, and keep the class instance alive.



来源:https://stackoverflow.com/questions/23020789/does-passing-a-method-of-one-object-to-another-object-keep-the-first-object-aliv

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!