Я отправляю это, чтобы быть педантичным. Мне не нравится интерфейс к Словарьу, потому что есть стоимость этого очень общего вида доступа - если ваш наиболее распространенный случай касается элемента, который уже существует, вы должны хешировать и искать свое значение 3 раза. Не верьте мне? Я написал решение DK здесь:
static void AddInc(Dictionary<string, int> dict, string s)
{
if (dict.ContainsKey(s))
{
dict[s]++;
}
else
{
dict.Add(s, 1);
}
}
Положено в IL - вы получите это:
L_0000: nop
L_0001: ldarg.0
L_0002: ldarg.1
L_0003: callvirt instance bool [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::ContainsKey(!0)
L_0008: ldc.i4.0
L_0009: ceq
L_000b: stloc.0
L_000c: ldloc.0
L_000d: brtrue.s L_0028
L_000f: nop
L_0010: ldarg.0
L_0011: dup
L_0012: stloc.1
L_0013: ldarg.1
L_0014: dup
L_0015: stloc.2
L_0016: ldloc.1
L_0017: ldloc.2
L_0018: callvirt instance !1 [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::get_Item(!0)
L_001d: ldc.i4.1
L_001e: add
L_001f: callvirt instance void [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::set_Item(!0, !1)
L_0024: nop
L_0025: nop
L_0026: br.s L_0033
L_0028: nop
L_0029: ldarg.0
L_002a: ldarg.1
L_002b: ldc.i4.1
L_002c: callvirt instance void [mscorlib]System.Collections.Generic.Dictionary`2<string, int32>::Add(!0, !1)
L_0031: nop
L_0032: nop
L_0033: ret
, который призывает ContainsKey, get_item и set_item, все из которых хэш и посмотреть вверх.
Я написал что-то менее симпатичное, которое использует класс, который содержит int, и класс позволяет вам его побочным эффектом (вы не можете действительно использовать структуру без какого-либо одного штрафа из-за семантики копирования копированием).
class IntegerHolder {
public IntegerHolder(int x) { i = x; }
public int i;
}
static void AddInc2(Dictionary<string, IntegerHolder> dict, string s)
{
IntegerHolder holder = dict[s];
if (holder != null)
{
holder.i++;
}
else
{
dict.Add(s, new IntegerHolder(1));
}
}
Это дает следующий IL:
L_0000: nop
L_0001: ldarg.0
L_0002: ldarg.1
L_0003: callvirt instance !1 [mscorlib]System.Collections.Generic.Dictionary`2<string, class AddableDictionary.IntegerHolder>::get_Item(!0)
L_0008: stloc.0
L_0009: ldloc.0
L_000a: ldnull
L_000b: ceq
L_000d: stloc.1
L_000e: ldloc.1
L_000f: brtrue.s L_0023
L_0011: nop
L_0012: ldloc.0
L_0013: dup
L_0014: ldfld int32 AddableDictionary.IntegerHolder::i
L_0019: ldc.i4.1
L_001a: add
L_001b: stfld int32 AddableDictionary.IntegerHolder::i
L_0020: nop
L_0021: br.s L_0033
L_0023: nop
L_0024: ldarg.0
L_0025: ldarg.1
L_0026: ldc.i4.1
L_0027: newobj instance void AddableDictionary.IntegerHolder::.ctor(int32)
L_002c: callvirt instance void [mscorlib]System.Collections.Generic.Dictionary`2<string, class AddableDictionary.IntegerHolder>::Add(!0, !1)
L_0031: nop
L_0032: nop
L_0033: ret
Что вызывает get_item раз - нет никакого дополнительного хеширования в случае объекта настоящего. Я немного запутался и сделал полевым, чтобы избежать вызова метода доступа к собственности.
Если бы это было, я бы обернуть эту общую функциональность в своем классе и скрыть класс IntegerHolder от общественности - вот ограниченная версия:
public class CountableItem<T>
{
private class IntegerHolder
{
public int i;
public IntegerHolder() { i = 1; }
}
Dictionary<T, IntegerHolder> dict = new Dictionary<T, IntegerHolder>();
public void Add(T key)
{
IntegerHolder val = dict[key];
if (val != null)
val.i++;
else
dict.Add(key, new IntegerHolder());
}
public void Clear()
{
dict.Clear();
}
public int Count(T key)
{
IntegerHolder val = dict[key];
if (val != null)
return val.i;
return 0;
}
// TODO - write the IEnumerable accessor.
}
Хорошо, ваше решение, кажется, работает. Что вы думаете о Альтернативе словаря? Кроме того, что, если я просто сделал (int) htColors [color] + 1, изменит ли это ключ или значение? – Xaisoft
Спасибо за помощь в HashTable. Похоже, я поеду с Словарем. – Xaisoft
Кто-то может исправить меня, если я ошибаюсь здесь, но я считаю, что автоматический бокс/распаковка происходит для любого типа значений, который перемещается в кучу, даже (в этом случае) ints в типизированном словаре (Dictionary). Какой словарь устраняет, это беспорядок от кастинга. –