在优化代码的时候,发现这样一段写法
public class Test : MonoBehaviour
{
public List<int> List = new List<int>();
private void Awake()
{
}
void Start()
{
foreach (var num in List)
{
//Do Something;
}
}
}
由于List是可以序列化的,于是在界面上就会如下所示:
好了,问题了来了,在运行时,我们自己New的List和外部传进来的List,是同一个List吗?如果没有,是否意味着我们浪费了一次GC.Alloc?
为了方面测试,我们新写一个类,名字叫做XList,我们重写类的构造函数,让类在构造函数中打印自己的HashCode
public class XList<T> : List<T>
{
public XList() : base()
{
Debug.LogError("New XList : " + GetHashCode());
}
}
然后修改测试代码:
public class Test : MonoBehaviour
{
public List<int> List = new XList<int>();
private void Awake()
{
Debug.LogError("Awake" + List.GetHashCode());
}
// Start is called before the first frame update
void Start()
{
Debug.LogError("Start" + List.GetHashCode());
}
}
运行代码:
我们可以发现,确实Unity总共New了两次List对象,并且都是在Awake之前。通过对比HashCode可知,第一次是我们默认New的空对象,第二次是UnityNew出来的并完成了反序列化。
因此我们就浪费了一次GC.Alloc
那如果我们自己不new对象,在面板上也放着不管,那这个List是null还是一个为0的对象呢?是为0的对象。所以安全性也不存在问题。
最终修改代码:
public class Test : MonoBehaviour
{
public List<int> List;
private void Awake()
{
Debug.LogError("Awake" + List.GetHashCode());
}
// Start is called before the first frame update
void Start()
{
Debug.LogError("Start" + List.GetHashCode());
}
}
运行:
由于此时List失去了实际的XList类型,因此XList的构造函数不再被调用。不过我们还是可以推测出,我们确实节省了一次GC分配
搜索
复制