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

问题:我现在有一个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吧。不用管内存回收的事情。

爽!

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页