上篇文章《【Unity优化】Unity中究竟能不能使用foreach?》发表之后,曾经有网友说,在他的不同的Unity版本上,发现了泛型List无论使用foreach还是GetEnumerator均会产生GC的情况,这就有点尴尬了。由于它本身就是Mono编译器和相应.net库才能决定的原因,这就使得在使用系统提供的List时,又能最终摆脱GC的纠缠变得很困难。于是抓耳挠腮,翻出差不多六七年为Java代码写的动态数组,然后大肆修改一番。最终好像终于逃离GC的魔咒。
先奉上代码:
自定义的List
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace AndrewBox.Math
{
/// <summary>
/// 动态数组
/// @author AndrewFan
/// </summary>
/// <typeparam name="T">任意类型</typeparam>
public class AB_List<T> :IEnumerable<T>
{
protected int m_capacity=10; // 容量
protected T[] m_items;// 内部数组
protected int m_length;// 存放的单元个数
protected int m_mayIdleID;// 可能空闲的单元下标
protected IEnumerator<T>[] m_enumerators; //枚举器组
protected bool[] m_enumStates;//枚举器组当前占用状态
public AB_List()
{
init(5);
}
public AB_List(int capacity,int enumCount=5)
{
init(enumCount);
}
protected void init(int enumCount)
{
m_capacity = m_capacity<10?10:m_capacity;
enumCount = enumCount < 5 ? 5 : enumCount;
m_items = new T[m_capacity];
if (m_enumerators == null)
{
m_enumerators = new IEnumerator<T>[enumCount];
m_enumStates = new bool[enumCount];
for (int i = 0; i < m_enumerators.Length; i++)
{
m_enumerators[i] = new ABEnumerator<T>(this,i);
}
}
}
/// <summary>
/// 增加单元
/// </summary>
/// <param name="element">添加的单元</param>
public virtual void Add(T element)
{
increaseCapacity();
// 赋值
m_items[m_length] = element;
m_length++;
}
/// <summary>
/// 插入单元
/// </summary>
/// <param name="index">插入位置</param>
/// <param name="element">单元</param>
/// <returns>操作是否成功</returns>
public virtual bool Insert(int index, T element)
{
if (index < 0)
{
return false;
}
if (index >= m_length)
{
Add(element);
return true;
}
increaseCapacity();
// 向后拷贝
// for(int i=length;i>index;i--)
// {
// datas[i]=datas[i-1];
// }
System.Array.Copy(m_items, index, m_items, index + 1, m_length - index);
m_items[index] = element;
m_length++;
return true;
}
public virtual T this[int index]
{
get
{
//取位于某个位置的单元
if (index < 0 || index >= m_length)
{
throw new InvalidOperationException();
}
return m_items[index];
}
set
{
//设置位于某个位置的单元
if (index < 0 || index >= m_length)
{
throw new InvalidOperationException();
}
m_items[index] = value;
}
}
/// <summary>
/// 增长容量
/// </summary>
protected void increaseCapacity()
{
if (m_length >= m_capacity)
{
int newCapacity = m_c