- 先看代码:
public void Update()
{
DictionaryTest();
}
public void DictionaryTest()
{
if (!mBInited)
{
mBInited = true;
m_States.Add(State.None, 0);
m_States.Add(State.Start, 0);
m_States.Add(State.Stop, 0);
}
int none = m_States[State.None];
}
private bool mBInited = false;
Dictionary<State, int> m_States = new Dictionary<State, int>();
2.运行结果(内存消耗)
3.原因分析
先看Dictionary
[__DynamicallyInvokable]
public TValue this[TKey key]
{
[__DynamicallyInvokable]
get
{
int num = this.FindEntry(key);
if (num >= 0)
{
return this.entries[num].value;
}
ThrowHelper.ThrowKeyNotFoundException();
return default(TValue);
}
[__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
set
{
this.Insert(key, value, false);
}
}
// System.Collections.Generic.Dictionary<TKey, TValue>
private int FindEntry(TKey key)
{
if (key == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
}
if (this.buckets != null)
{
int num = this.comparer.GetHashCode(key) & 2147483647;
for (int i = this.buckets[num % this.buckets.Length]; i >= 0; i = this.entries[i].next)
{
if (this.entries[i].hashCode == num && this.comparer.Equals(this.entries[i].key, key))
{
return i;
}
}
}
return -1;
}
最终的消耗是在 FindEntry(TKey key)中的this.comparer.GetHashCode(key),而compare这个泛型函数会导致内存的分配涉及到反射typeof(Tkey),
// System.Collections.Generic.Dictionary<TKey, TValue>
private IEqualityComparer<TKey> comparer;
ublic static Comparer<T> Default
{
[__DynamicallyInvokable]
get
{
Comparer<T> comparer = Comparer<T>.defaultComparer;
if (comparer == null)
{
comparer = Comparer<T>.CreateComparer();
Comparer<T>.defaultComparer = comparer;
}
return comparer;
}
}
private static Comparer<T> CreateComparer()
{
RuntimeType runtimeType = (RuntimeType)typeof(T);
if (typeof(IComparable<T>).IsAssignableFrom(runtimeType))
{
return (Comparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(GenericComparer<int>), runtimeType);
}
if (runtimeType.IsGenericType && runtimeType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
RuntimeType runtimeType2 = (RuntimeType)runtimeType.GetGenericArguments()[0];
if (typeof(IComparable<>).MakeGenericType(new Type[]
{
runtimeType2
}).IsAssignableFrom(runtimeType2))
{
return (Comparer<T>)RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableComparer<int>), runtimeType2);
}
}
return new ObjectComparer<T>();
}