sadece değerini etkilemez olmak olmak. Sözlükle ara yüzlemeyi sevmiyorum çünkü bu çok yaygın erişim türüne bir maliyet var - en yaygın durumunuz zaten var olan bir öğeye dokunuyorsa, 3 kez değerinizi almalı ve bulmalısınız. Bana inanma Bu mesajı alır -
IL koymak
static void AddInc(Dictionary<string, int> dict, string s)
{
if (dict.ContainsKey(s))
{
dict[s]++;
}
else
{
dict.Add(s, 1);
}
}
:
ContainsKey, Get_Item ve set_item çağrıları
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
, hepsi karma ve bakmak arasında burada DK çözümünü yazdı.
Int içeren bir sınıf kullanan güzel bir şey yazdım ve sınıf onu yan etki yapmanıza izin veriyor (struct struct semantics'i nedeniyle aynı cezaya çarpmadan gerçekten bir struct kullanamazsınız).
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));
}
}
Bu size aşağıdaki IL verir: Get_Item kez çağırır
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
- bir nesne mevcut durumunda hiçbir ek karma yoktur. Biraz alçakgönüllüyüm ve yöntemin mülkiyete erişimini engellemek için alanı kamusal hale getirdim. Yerinde olsaydım
, ben kendi sınıfının içine bu genel işlevselliğini sarın ve genel görünümden IntegerHolder sınıfını saklasın - burada sınırlı bir sürümü:
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, çözüm çalışıyor gibi gözüküyor. Sözlük alternatifi hakkında ne düşünüyorsunuz? Ayrıca, ne yapsaydım (int) htColors [color] + 1, anahtar veya değeri değiştirirse? – Xaisoft
HashTable ile ilgili yardım için teşekkürler. Sonuçta bir Sözlük ile gideceğim gibi görünüyor. – Xaisoft
Burada yanlış olduğumda birisi beni düzeltebilir, ancak otomatik kutulama/kutulama işleminin, yığına taşınan herhangi bir değer türü için (hatta bu durumda) yazılı bir sözlükte (Sözlük) ints için gerçekleştiğine inanıyorum. Sözlük ne yaparsa dökümden dağılır. –