Unity C#開發中,常常用到Enum或Struct等類型作為Dictionary的key,或List的元素,即: List<EnumType>,Dictionary<EnumType, ValueType>,List<StructType>,Dictionary<StructType, Valu ...
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()調用。