C# for、while和foreach遍历产生GC

最近在网上看到了有关于Foreach遍历会产生GC的文章今天测试了下,在这里记录下怕忘记。

先上测试代码

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class People
{
    public string Name;
    public int Age;
}
public class FontTextureSet : MonoBehaviour
{
    int[] tempsInts = new[] { 1, 3, 4, 5, 6 };
    private People[] peoples;
    private List peoplesList;
    private List intList; 
    private Dictionary peopleDictionary;
    private Dictionary intDictionary; 
    private int tem;
	// Use this for initialization
    void Awake()
    {
        peoples = new People[5];
        peoplesList = new List();
        intList = new List();
        peopleDictionary = new Dictionary();
        intDictionary = new Dictionary();
        for (int i = 0; i < 5; i++)
        {
            People people = new People();
            people.Age = i;
            people.Name = ((char) 'A' + i).ToString();
            peoples[i] = people;
            peoplesList.Add(people);
            peopleDictionary.Add(i, people);
            intDictionary.Add(i,i);
            intList.Add(i);
        }
	}

    void Update()
    {
        Profiler.BeginSample("Foreach Int Array");
        foreach (int v in tempsInts)
        {
            tem = v;
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach People Array");
        foreach (People p in peoples)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foeach Int List");
        foreach (int i in intList)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach People List");
        foreach (People people in peoplesList)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach People Dictionary");
        foreach (KeyValuePair keyValuePair in peopleDictionary)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foeach peopleDictionary.Values");
        foreach (People people in peopleDictionary.Values)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach Int Dictionary");
        foreach (KeyValuePair keyValuePair in intDictionary)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach intDictionary.Values");
        foreach (int value in intDictionary.Values)
        {
            
        }
        Profiler.EndSample();
    }
}
ok,在来看看GC情况

C# for、while和foreach遍历产生GC_第1张图片

哦 my god 这是真的吗,除了数组的遍历其他都产生了GC,这要是真的在Update里用了foreach遍历Directionary和List那不是要疯了,这代码要是让主程看到他肯定要哭,好吧,废话不多说,先来分析一下结果:

1、就是foreach变量数组不会产生GC,遍历Directionary和List都会产生GC

2、foreach遍历List产生GC是24B,Directionary是28B,注意Directionary遍历有多种这里我只测试了两种用foreach的遍历方法,有Directionary.Values遍历会产生40B的GC

3、GC的产生与数据类型无关,与数据结构有关


接下来能是for和while其实他们两差不多在遍历Directionary时都会产生GC,有一种情况除外,先来看测试代码

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class People
{
    public string Name;
    public int Age;
}
public class FontTextureSet : MonoBehaviour
{
    int[] tempsInts = new[] { 1, 3, 4, 5, 6 };
    private People[] peoples;
    private List peoplesList;
    private List intList; 
    private Dictionary peopleDictionary;
    private Dictionary intDictionary; 
    private int tem;
	// Use this for initialization
    void Awake()
    {
        peoples = new People[5];
        peoplesList = new List();
        intList = new List();
        peopleDictionary = new Dictionary();
        intDictionary = new Dictionary();
        for (int i = 0; i < 5; i++)
        {
            People people = new People();
            people.Age = i;
            people.Name = ((char) 'A' + i).ToString();
            peoples[i] = people;
            peoplesList.Add(people);
            peopleDictionary.Add(i, people);
            intDictionary.Add(i,i);
            intList.Add(i);
        }
	}

    void Update()
    {
        Profiler.BeginSample("For Int Array");
        for (int i = 0; i < tempsInts.Length; i++)
        {
            //tempsInts[i];
        }
        Profiler.EndSample();

        Profiler.BeginSample("For People Array");
        for (int i=0; i

结果图如下:

C# for、while和foreach遍历产生GC_第2张图片

结论:

1、Dictionary不管是for、while还是foreach都会产生GC都是28B(注意这里没有用var这个关键字,下面我会对用var的遍历做测试)

2、For遍历Dictionary.Values产生的GC是72B,比foreach多32B

3、For和while遍历数组和List都不会产生GC


上面我提到了var这个关键字,ok,下面我们就对这个做个测试

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class People
{
    public string Name;
    public int Age;
}
public class FontTextureSet : MonoBehaviour
{
    int[] tempsInts = new[] { 1, 3, 4, 5, 6 };
    private People[] peoples;
    private List peoplesList;
    private List intList; 
    private Dictionary peopleDictionary;
    private Dictionary intDictionary; 
    private int tem;
	// Use this for initialization
    void Awake()
    {
        peoples = new People[5];
        peoplesList = new List();
        intList = new List();
        peopleDictionary = new Dictionary();
        intDictionary = new Dictionary();
        for (int i = 0; i < 5; i++)
        {
            People people = new People();
            people.Age = i;
            people.Name = ((char) 'A' + i).ToString();
            peoples[i] = people;
            peoplesList.Add(people);
            peopleDictionary.Add(i, people);
            intDictionary.Add(i,i);
            intList.Add(i);
        }
	}

    void Update()
    {
        Profiler.BeginSample("Foreach Var Dictionary");
        foreach (var VARIABLE in peopleDictionary)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach Var Dictionary.Values");
        foreach (var value in peopleDictionary.Values)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("Foreach Var List");
        foreach (var people in peoplesList)
        {
            
        }
        Profiler.EndSample();

        Profiler.BeginSample("For Var Dictionary");
        var e = peopleDictionary.GetEnumerator();
        e.MoveNext();
        for (int i=0; i
结果如下图所示:

可以看出对于foreach来说没什么变化,但对for和while来说意义非凡啊,Directionary的遍历没有GC了。

OK,最后来做个总结:

1、遍历不要用foreach,全用for和while

2、遍历Dictionary是有一下两种方式的一种:

        var e = peopleDictionary.GetEnumerator();
        e.MoveNext();
        for (int i=0; i

以上的测试只是简单测试不全,但已经达到目的了:就是以后遍历怎么遍历不会产生GC。Ok,今天就这么多,最后还有疑问,就是他们怎么产生GC的,有些为什么又没有GC? 哪位大神知道,求告知,谢谢!!!!!!

你可能感兴趣的:(编程,遍历,for,while,foreach,GC)