Unity中的拆/装箱操作引发的GC问题解决方案
Unity C#开发中,常常用到Enum或Struct等类型作为Dictionary的key,或List的元素,即:
List<EnumType>,Dictionary<EnumType, ValueType>,List<StructType>,Dictionary<StructType, ValueType>。
在List的Contains()、Dictionary的ContainsKey()或[]操作时,会调用Equals()和GetHasCode(),从而对Enum或Struct类型进行装箱操作,产生GC问题。
解决方案:
1、Struct,override GetHasCode()并实现IEquatable<T>即可。例如:
/// <summary> /// sizeof(KeyStruct) = 12B /// 测试Dictionary的Contains()和[] /// 1.不override GetHashCode()和实现IEquatable<T> /// Contains():84B /// []:84B /// 2.只实现实现IEquatable<T> /// Contains():28B /// []:28B /// []:84B /// 3.只override GetHashCode() /// Contains():56B /// []:56B /// 4.override GetHashCode()和实现IEquatable<T> /// Contains():0 /// []:0 /// </summary> struct KeyStruct : IEquatable<KeyStruct> { public int a; public int b; public int c; public KeyStruct(int a, int b, int c) { this.a = a; this.b = b; this.c = c; } public override int GetHashCode() { return this.a * 100 + this.b * 10 + this.c; } public bool Equals(KeyStruct obj) { return this.a == obj.a && this.b == obj.b && this.c == obj.c; } }
2、Enum类型由于不能override和implement接口,需要使用其他方法。
当作为Dictionary key使用时,可以为Enum定义一个专用比较器,如下:
enum KeyEnum { K1, K2, K3, K4, } struct KeyEnumComparer : IEqualityComparer<KeyEnum> { public bool Equals(KeyEnum x, KeyEnum y) { return x == y; } public int GetHashCode(KeyEnum obj) { // you need to do some thinking here, return (int)obj; } } Dictionary<KeyEnum, KeyEnum> enumDict2 = new Dictionary<KeyEnum, KeyEnum>(new KeyEnumComparer()) { {KeyEnum.K1,KeyEnum.K1}, {KeyEnum.K2,KeyEnum.K1}, {KeyEnum.K3,KeyEnum.K1}, {KeyEnum.K4,KeyEnum.K1} };
List中使用Enum,由于无法在构造函数中传入自定义比较器,推荐使用List.Exists(e => e == KeyEnum.K1)代替List.Contains(KeyEnum.K1),以避免Equals()调用。
作者:dongzee
出处:http://www.cnblogs.com/dongzee
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接
如有问题,可以通过 dongzee1984#gmail.com 联系我,非常感谢。