List <t> .Clear - 是否必须调用?</t>

时间:2010-06-19 22:08:34

标签: c# generics garbage-collection list

所以我过去一周在我的项目中遇到了另一个内存问题。我尝试了几个内存分析器,但没有什么能让我深入了解导致次要内存泄漏的原因。以下代码证明了它的原因:

private void DeleteAll( FlowLayoutPanel flp)
{
    List<ImageControl> AllList = GetAllList(flp);
    List<ImageControl> LockedList = GetLockedList(flp);

    for (int i = 0; i < LockedList.Count; i++)
    {
        AllList.Remove(LockedList[i]);
    }

    flp.SuspendLayout();

    for (int i = 0; i < AllList.Count; i++)
    {
        flp.Controls.Remove(AllList[i]);
    }

    DisposeList(AllList);

    flp.ResumeLayout();

}

在代码中,ImageControl是一个UserControl,上面的整个方法只是从FlowLayoutPanel中删除ImageControls。 DisposList()方法只为传递给它的列表中的所有控件调用ImageControl.Dispose()。

现在,我认为一旦这个方法退出,AllList将超出范围,因此它对ImageControl的所有引用都将不存在。所以GC会做这件事。但事实并非如此。我发现它需要

AllList.Clear();

在AllList超出范围之前添加到DeleteAll()方法的末尾。

那么您是否必须始终明确清除通用列表以释放资源?或者是我上面做错了什么?我想知道,因为我在这个项目中大量使用临时列表。

好的,这是GetAllList方法。对我来说看起来不是问题:

private List<ImageControl> GetAllList(FlowLayoutPanel flp)
{
    List<ImageControl> List = new List<ImageControl>();

    for (int i = 0; i < flp.Controls.Count; i++)
    {
        List.Add((ImageControl)flp.Controls[i]);
    }

    return List;
}
顺便说一句,如果你在这里看到我的最后几个话题,我一直在努力解决内存泄漏问题,以成为一名熟练的c#程序员:)我添加了DisposeList()方法,因为我读过Dispose()应该被调用在任何实现IDisposable的对象上,UserControl都这样做。我还需要一种方法来修复ToolStrip类(ImageControl包含的)的“bug”,它会导致资源保留,除非Visible属性在被销毁之前设置为false。所以我已经重写了ImageControl的Dispose方法来做到这一点。

哦,DisposeList()也取消订阅事件处理程序:

private void DisposeList( List<ImageControl> IC )
{
    for (int i=0;i<IC.Count;i++)
    {
        IC[i].DoEvent -= ImageButtonClick;
        IC[i].Dispose();
    }
}

2 个答案:

答案 0 :(得分:4)

如果AllList是对列表和列表中元素的唯一引用,那么一旦退出DeleteAll方法,列表及其所有元素就有资格进行垃圾回收。< / p>

如果调用AllList.Clear()会产生影响,那么我会得出结论,在代码中的其他地方存在对相同列表的引用。也许仔细看看GetAllList()方法会给出一个线索。

答案 1 :(得分:1)

您不必清除列表。你可以分享你的GetAllList()函数吗?你甚至需要一个相应的“DisposeList()”方法的事实告诉我,那里可能存在副作用,在某处保留对你的列表的引用。

另外,我会简化这样的代码:

private void DeleteAll( FlowLayoutPanel flp)
{
    var UnlockedImages = flp.Controls.OfType<ImageControl>().Except(GetLockedList(flp));

    flp.SuspendLayout();

    foreach (ImageControl ic in UnlockedImages)
    {
        flp.Controls.Remove(ic);
    }

    flp.ResumeLayout();
}