Je poste ce pour être pédant. Je n'aime pas l'interfaçage avec le dictionnaire car il y a un coût pour ce type d'accès très courant - si votre cas le plus courant touche un élément qui existe déjà, vous devez hacher et rechercher votre valeur 3 fois. Ne me crois pas? Je ici écrit la solution DK:
static void AddInc(Dictionary<string, int> dict, string s)
{
if (dict.ContainsKey(s))
{
dict[s]++;
}
else
{
dict.Add(s, 1);
}
}
Lorsque mis en IL - vous obtenez ceci:
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
qui appelle à ContainsKey, get_item et set_item, dont tous hachage et rechercher. J'ai écrit quelque chose de moins joli qui utilise une classe qui contient un int et la classe vous permet de l'affecter latéralement (vous ne pouvez pas vraiment utiliser une structure sans encourir la même pénalité à cause de la sémantique de copie de structure).
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));
}
}
Cela vous donne l'IL suivante:
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
qui appelle get_item une fois - il n'y a pas supplémentaire dans le hachage cas d'un objet présent. J'ai été un peu louche et j'ai rendu le champ public pour éviter les appels de méthode pour l'accès à la propriété.
Si c'était moi, je conclurai cette fonctionnalité globale dans sa propre classe et cacher la classe IntegerHolder de la vue du public - voici une version limitée:
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.
}
Ok, votre solution semble fonctionner. Que penses-tu de l'alternative du dictionnaire? Aussi, si je faisais juste (int) htColors [couleur] + 1, cela changerait-il la clé ou la valeur? – Xaisoft
Merci pour l'aide avec le HashTable. Il semble que je vais aller avec un dictionnaire après tout. – Xaisoft
Quelqu'un peut me corriger si je me trompe ici, mais je crois que boxing/unboxing automatique se produit pour tout type de valeur qui est déplacé vers le tas, même (dans ce cas) ints dans un dictionnaire typé (Dictionary). Quel Dictionnaire élimine est l'encombrement de la coulée. –