这可能是一个语义问题,但也许不是,所以我问:以下两个摘要之间是否有明显的不同?

public Parent()
{
    Child newChild = new Child();
    newChild.RequestSpecialEvent += (sender, e) =>
    {
        newChild.DoMagic();
    }
}


要么

public Parent()
{
    Child newChild = new Child();
    newChild.RequestSpecialEvent += (sender, e) =>
    {
        ((Child)sender).DoMagic();
    }
}


明显的区别是选项1本身具有自我引用,而选项2则对对象执行强制转换。在性能方面,我希望演员阵容更昂贵。

但是,我在理论上认为,在选项1中,从技术上讲,它是“父母”,持有对“ newChild”的引用(通过在Parent中定义的委托),所以即使newChild消失了(newChild = null或类似的东西), newChild对象不能被垃圾回收(gc'ed),因为Parent已定义了一个仍附加到它的委托。仅当Parent最终离开时,才可以对newChild进行操作。

但是,在选项2中,父级永远不会为newChild创建这样的“硬引用”,因此当newChild = null发生时,它确实可以立即进行gc处理。

我更喜欢选项1的简洁性和可读性,但担心选项2会更好。有什么想法吗?我的理论是正确的还是偏离基准的?是否有其他方法或更优选的方法(带有合理的推理)来声明与父/子类的相同事件侦听器关系?

回应@StriplingWarrior:

关于垃圾收集,我仍然有些怀疑。委托引用了newChild,所以对我来说,直到委托消失,newChild才能消失。现在,如果newChild离开,则代表将离开...但是newChild直到代表离开后才能消失!似乎是圆形的(几乎)。似乎必须要这样:

//newChild = null;
//This alone won't truly free up the newChild object because the delegate still
//points to the newChild object.

//Instead, this has to happen
newChild.RequestSpecialEvent = null; //destroys circular reference to newChild
newChild = null; //truly lets newChild object be gc'd


或者说“ newChild = null;”仅,newChild.RequestSpecialEvent停止指向委托,这使委托消失,然后让newChild消失?也许我只是说说了你的答案。 :)

最佳答案

您的想法似乎有些混乱,只是我敢肯定newChild仍可以在选项1中进行垃圾收集,因为引用它的委托本身仅由newChild本身的处理程序引用。

这两个代码段在功能上是等效的,由于委托中有额外的引用,因此选项1使用了更多的内存,但是由于避免了强制转换,因此调用时运行的速度稍快一些。两种方法之间的差异都可以忽略不计,以至于我建议您使用最干净的方法(如果您问我,则排名第一)。

我唯一会采用类似#2的方法是,如果您要将同一委托应用于多个控件。在这种情况下,最终将使用更少的内存:

var handler = new RequestSpecialEventHandler((sender, e) =>
    {
        ((Child)sender).DoMagic();
    });
foreach(var child in children)
{
    child.RequestSpecialEvent += handler;
}


还有一点需要注意的是,由于选项#1引用了newChild变量,如果该变量的值在方法中稍后更改,则在调用处理程序时将使用新值。例如,在此示例中:

foreach(var child in children)
{
    child.RequestSpecialEvent += (sender, e) =>
        {
            // BEWARE: Don't do this! Modified closure!
            child.DoMagic();
        };
}


...每当事件在这些子级上触发时,“ Magic”将仅在children集合中的最后一个子级上执行N次。

10-06 12:05