通用标签

由于delegate捕获了可变的this._bar,它是否隐含地保留了B的实例?会通过事件处理程序引用B的实例,并通过A实例的实例捕获变量吗?

如果_barAttachToAEvent方法的局部变量,会有所不同吗?

由于在我的情况下,基因编码实例的寿命比基因编码实例的寿命长得多,并且远小于基因编码实例,所以我担心这样做会导致“内存泄漏”。

有帮助吗?

解决方案

通过查看由编译器生成的代码,这很容易理解,该代码类似于: 通用标签

可以清楚地看到,创建的委托是 instance 委托(将对象的实例方法作为目标),因此必须保留对该对象实例的引用。

由于委托捕获了变量this._bar,它是否隐式地保存到 B的实例?

实际上,匿名方法仅捕获this(而不是this._bar)。从生成的代码可以看出,构造的委托确实将保留对B实例的引用。它必须;每当执行委托时,如何按需读取该字段?请记住,捕获了变量,而不是

因为在我的情况下,A的寿命更长,并且寿命更短 我比B实例要担心会导致“内存泄漏” 这个。

是的,您有充分的理由要做。只要A实例是可访问的,B事件订阅者仍将是可访问的。如果您不想看待弱事件,则需要重写它,以便在不再需要该处理程序时将其注销。

如果_bar是 AttachToAEvent方法?

是的,因为捕获的变量将成为本地基因标签代码而不是本地基因标签代码。 但是假设bar是一个实例方法,那么您的“问题”(如果您想这样想的话)就变得更糟了。现在,编译器需要生成一个事件侦听器,以“记住”本地和包含其的this对象实例。

这是通过创建一个闭包对象并将其(实际上是它的一个实例方法)作为委托的目标来实现的。 通用标签

其他提示

Ani的答案是正确的。总结并添加一些细节:

由于委托捕获了变量this._bar,它是否隐式地持有B的实例?

是的。 “此”被捕获。

是否将通过事件处理程序引用B的实例,并通过A的实例捕获变量?

是的

如果_bar是AttachToAEvent方法的局部变量,会有所不同吗?

是的。在这种情况下,闭包对象将保留在本地;本地将被实现为封闭的领域。

由于在我的情况下,A实例的寿命比B实例长得多,并且比B实例小得多,因此我担心这样做会导致“内存泄漏”。

您绝对有权利担心。您的情况已经很糟,但是实际上,当您使用两个匿名函数时,情况可能会严重得多。现在,同一局部变量声明空间中的所有匿名函数都共享一个公共闭包,这意味着 all 封闭的外部变量(包括“ this”)的生存期可以扩展到。有关详细信息,请参见我关于该主题的文章:

http://blogs.msdn.com/b/ericlippert/archive/2007/06/06/fyi-c-and-vb-closures-are-per-scope.aspx

我们希望在假设的C#未来版本中解决此问题;我们可以更好地对闭包进行分区,而不是创建一个大的闭包。但是,这不会很快发生。

此外,C#5的“异步/等待”功能也可能会加剧当地人的寿命长于预期的情况。我们谁都不会为此感到兴奋,但是正如他们所说,完美是超凡脱俗的敌人。对于如何调整异步块的代码源来改善这种情况,我们有一些想法,但是没有任何希望。

如果您将匿名方法添加到事件中并希望对其进行引用,则必须将事件设置为null或将委托存储在列表中,以便以后可以从事件中“-=“”。

但是,是的,您可以从附加到事件的委托中引用的对象中获取“内存泄漏”。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top