您的位置:首页 > 编程语言 > C#

C#使用List.Clear()方法可以让GC回收内存吗?

2018-03-08 16:47 1021 查看
问题:我现在有一个list,里面放了若干对象,因为业务需要,程序运行后根据用户需求,要把list清空,再装入新的东西,每一次用之前都会清空它,然后装入新的东西,请问,内存是否会泄漏?测试:我设计一个list,清空用clear方法,装入新东西用add(new obj)。
public void GameInit()
{
PlayerCnt = 0;
PlayerList.Clear();
PileCnt = 0;
Pile.Clear();
DisPileCnt = 0;
DisPile.Clear();
}

public void GameStrat()
{
GameInit();
//准备新牌堆,洗牌
PileCnt = Card.DeckLength;
List<short> sort = new List<short>();
for (short i = 0; i < PileCnt; i++)
{
sort.Add(i);//0-207
}
Shuffle(sort);
for (short i = 0; i < PileCnt; i++)
{
Pile.Add(new Card(Card.Deck[sort[i]]));
}
}


使用按键调用这个方法,每一次调用循环10w次。
//menu-操作-重启游戏 的 事件
private void Menu_Restart_click(object sender, RoutedEventArgs e)
{
int i = 0;
for (; i < 100000; i++)
{
GameInst.GameStrat();
}
Console.WriteLine("Debug"+i);
}


通过任务管理器查看内存状态。刚打开app:

按下一次按键,运行10w次

多次按下按键,实验次数大于10次

实验结果表明,C#的GC对于本案例有较好的内存控制,第一次运行之后有内存上升,之后内存消耗非常稳定。分析,本例中,list中添加的对象为Card,每一次添加Card都是通过new的方法创建一个新的Card。Clear只是清空了list中对于这个Card对象的引用,并没有对每一张Card本身引用做null,但是,根据GC的官方信息,有两方面,1、每一张new出来的card只有list可以引用,clear之后,引用计数变为0,认为是垃圾。2、每一张new出来的card从list中移除后,从程序的数据树根就无法再次通过直接“爬树”的方法访问到,成为了程序数据树中不存在,但是总数据等级表中存在的东西(new一次GC会额外做一次登记),这样就会被认为是垃圾。
新的问题来了,我这个算法中有一个洗牌算法,洗牌算法原理参照我的上一篇blog
洗牌算法-Fisher–Yates算法为什么好?

这个洗牌算法代码如下:public static void Shuffle(List<short> list)
{
int length = list.Count;
short tmp, rdtmp;
Random rd = new Random();
for (int i = 0; i < length; i++)
{
rdtmp = (short)rd.Next(i, length);
//Console.WriteLine(i + ": " + rdtmp + " ");
tmp = list[rdtmp];
list[rdtmp] = list[i];
list[i] = tmp;
}
//rd = null;
} 这个里面有一个问题,每一次运行洗牌算法都需要一个random对象
Random rd = new Random();运行10w次就是new了10w次,从上面的内存分析可以看出,这个也被很好的控制了。
具体分析为,每一次new都生成了一个对象,然后每一次运行这段程序,rd都在不断的指向新的random对象,之前的random对象都变成了野的对象,因此,GC也能通过上述的两种方法发现老的random对象,实现回收,所以最后的
//rd = null;我直接注释掉了,因为不需要。
所以,放心的new吧。不用管内存回收的事情。
爽!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C# List GC