字典

时间:2016-11-22 20:25:19

标签: c# .net dictionary tuples

如果是字典,其中键是复杂的(值的组合) 例如,密钥可以是一对字符串和整数。

您建议将哪种数据类型用于密钥?我考虑了字典中大量读取时的性能和内存使用情况,分配繁重的数据类型可能不适合该任务。

我测试了4种不同的策略。

  1. 最天真的一个,使用字符串作为键并连接组件:

    int Read(string str, int num)
    {
        var key = str + "|" + num;
        return dict[key];
    }
    
  2. 使用元组表示密钥:

    int Read(string str, int num)
    {
        var key = new Tuple<string, int>(str, num);
        return dict[key];
    }
    
  3. 使用KeyValuePair表示密钥:

    int Read(string str, int num)
    {
        var key = new KeyValuePair<string, int>(str, num);
        return dict[key];
    }
    
  4. 我不喜欢第一种方法,带元组的那种方法看起来更优雅。 但是,Tuple与字符串没有那么不同,因为它们都是类,分配它们可能很昂贵。 KeyValuePair似乎是最可行的数据类型,但在运行一些测试后,我发现它的性能比字符串或元组差得多,现在看来KeyValuePair没有实现GetHashCode()。 然后我尝试实现我自己的“KeyValuePair”,它覆盖了Equals和GetHashCode():

    struct KVPair<K, V>
    {
        public K Key { get; set; }
    
        public V Value { get; set; }
    
        public KVPair(K key, V value)
        {
            Key = key;
            Value = value;
        }
    
        public override bool Equals(object obj)
        {
            if (!(obj is KVPair<K,V>))
            {
                return false;
            }
    
            KVPair<K, V> other = (KVPair<K, V>)obj;
            return Key.Equals(other.Key) &&
                Value.Equals(other.Value);
        }
    
        public override int GetHashCode()
        {
            int keyHash = Key.GetHashCode();
            int valHash = Value.GetHashCode();
    
            return (((keyHash << 5) + keyHash) ^ valHash);
        }
    }
    

    并将其用作我词典中的关键词:

        int Read(string str, int num)
        {
            var key = new KVPair<string, int>(str, num);
            return dict[key];
        }
    

    它似乎比字符串和元组选项表现更好,并且比原生KeyValuePair更好。

    我只是想听听你的建议。 我必须谨慎地实现自己的数据类型,因为FCL通常会处理这个问题。

1 个答案:

答案 0 :(得分:1)

我更喜欢使用具有相关属性名称的特定类型:

public class RowKey
{
    public string Title { get; set; }
    public int Id { get; set; }

    public RowKey()
    {
    }

    public RowKey(string title, int id)
    {
        Title = title;
        Id = id;
    }

    public override bool Equals(object obj)
    {
        if (!(obj is RowKey))
            return false;

        RowKey other = obj as RowKey;
        return Title.Equals(other.Title) && Id.Equals(other.Id);
    }
    public override int GetHashCode()
    {
        int titleHash = Title.GetHashCode();
        int idHash = Id.GetHashCode();

        return (((titleHash << 5) + titleHash) ^ idHash);
    }
}

阅读使用:

int Read(string str, int num)
{
    var key = new RowKey(str, num);
    return dict[key];
}