AddOrUpdate不更新

时间:2016-03-21 22:01:41

标签: c# concurrentdictionary

我有<byte[], int>

类型的并发字典list1

我遍历另一个字符串列表(_dict)的项目,如果该项目作为_dict中的键存在,我会增加其值;如果没有,我将其添加到foreach(byte[] item in list1) { _dict.AddOrUpdate(item, 1, (key, oldValue) => oldValue + 1); } 并将其值设置为1

_dict

问题是,即使该项目已存在于_dict中,它也会将其再次添加到 internal class someClass { public List<byte[]> list1 { get; set; } public ConcurrentDictionary<byte[], int> dict1 { get; set; } } class Program { static void Main(string[] args) { someClass obj = new someClass(); if (obj.list1 != null && obj.list1.Count > 0) { foreach (byte[] item in obj.list1) { // upsert operation (add if string not in dictionary; update by incrementing count if it does exist) obj.dict1.AddOrUpdate(item, 1, (key, oldValue) => oldValue + 1); } } } } 而不是更新。

我的代码出了什么问题?

更新了代码块

json_decode

2 个答案:

答案 0 :(得分:2)

使用byte []作为字典键是个坏主意,因为两个不同的字节数组将通过引用而不是内部数据进行比较。因此,如果你强烈需要byte []作为字典键,你应该为IEqualityComparer接口编写自己的类。例如:

public class ByteArrayComparer : IEqualityComparer<byte[]> {
  public bool Equals(byte[] x, byte[] y) {
    if ( x == null || x == null ) {
      return x.length == y.length;
    }
    return x.SequenceEqual(y);
  }
  public int GetHashCode(byte[] key) {
    return key.Sum(b => b);
  }
}

答案 1 :(得分:2)

由于您已将密钥类型从string更改为byte[],现在您看到的行为是正确的(最初,问题包含string个密钥)。

由于:

字典使用默认的IEqualityComparer来比较密钥,在byte[]的情况下,只是比较参考。

由于两个byte[]数组是两个不同的对象,即使它们包含相同的元素,它们也会被视为不同的键。

考虑自己创建一个IEqualityComparer实现并在此构造函数中使用它:

public ConcurrentDictionary(
    IEqualityComparer<TKey> comparer
)

编辑: 这是一个有效的例子:

public class ByteArrayComparer : IEqualityComparer<byte[]>
{
    public bool Equals(byte[] x, byte[] y)
    {
        if (x == null || y == null)     
            return false;       

        if(x.Length != y.Length)
            return false;

        return x.SequenceEqual(y);
    }

    public int GetHashCode(byte[] array)
    {
        unchecked
        {
            return array.Aggregate(17, (v, b) => v * 23 + b.GetHashCode(), v => v);
        }
    }
}

internal class someClass
{
    public List<byte[]> list1 = new List<byte[]>();
    public ConcurrentDictionary<byte[], int> dict1  = new ConcurrentDictionary<byte[], int>(new ByteArrayComparer());
}

void Main()
{
    someClass obj = new someClass();

    obj.list1.Add(new byte[] { 1, 2 });
    obj.list1.Add(new byte[] { 1, 2 });
    obj.list1.Add(new byte[] { 1, 2 });
    obj.list1.Add(new byte[] { 2, 3 });
    obj.list1.Add(new byte[] { 2, 3 });
    obj.list1.Add(new byte[] { 3, 4 });

    if (obj.list1 != null && obj.list1.Count > 0)
    {
        foreach (byte[] item in obj.list1)
        {
            // upsert operation (add if string not in dictionary; update by incrementing count if it does exist)
            obj.dict1.AddOrUpdate(item, 1, (key, oldValue) => oldValue + 1);
        }
    }
}

obj.dict1的最终内容将是:

Key 01 02 
Value 3 

Key 02 03 
Value 2 

Key 03 04 
Value 1