C#中Dictionaries的替代方法是什么,允许重复键?

时间:2014-12-15 14:00:20

标签: c# dictionary collections

我有一个方法可以返回曾参与某些项目的技术人员小组,例如:

project 1 | John
project 1 | Tim
project 2 | John
project 2 | Dave

我最初尝试创建一个通常是我的键值对集合的字典,但在这种情况下我无法使用它,因为我无法使用重复键(项目)。我可以使用什么替代方案?

我唯一的想法是创建一个Dictionary<Project, List<Technicians>>,但有更容易的东西吗?

5 个答案:

答案 0 :(得分:44)

在您的情况下,相同的密钥与多个值相关,因此标准字典不适合。您可以将其声明为Dictionary<Key, List<Values>>

但是,您也可以使用:

Lookup类,

  

表示每个映射到一个或多个值的键集合。

为此需要3.5及更多框架。

答案 1 :(得分:13)

您需要的是Project与一名或多名技术人员之间的关系:

public class Project
{
    public ICollection<Technician> Technicians { get; set; }
}

var project = new Project();
project.Technicians = new List<Technician>()
{
    new Technician(),
    new Technician()
};

你的物体应该反映现实生活中的关系。

作为旁注,您可能有兴趣阅读Domain-driven design

public void LoadTechnicians(Project project)
{
    List<Technician> techs = new List<Technician>();

    // query the database and map Technician objects

    // Set the "Technicians" property
    project.Technicians = techs;
}

答案 2 :(得分:12)

an experimental NuGet package from MS that contains MultiValueDictionary

基本上,它与Dictionary<Project, List<Technicians>>类似,只是每次访问时都不必重复所有逻辑来管理List

答案 3 :(得分:4)

我认为您的解决方案没有任何问题。毕竟,您可以按项目轻松访问所有团队成员。但另外,您可以尝试List<KeyValuePair<Project, Technician>>。您保持键值关系,但不限制不重复的键。你现在拥有的东西要简单得多吗?取决于用例。

或者,您可以在自定义集合实现后隐藏此结构。

答案 4 :(得分:0)

我已经从this post复制了自己的答案。

它很容易“滚动你自己的&#34;允许&#34;重复键&#34;的字典版本。条目。这是一个简单的粗略实现。您可能需要考虑在IDictionary<T>上添加对大多数(如果不是全部)的支持。

public class MultiMap<TKey,TValue>
{
    private readonly Dictionary<TKey,IList<TValue>> storage;

    public MultiMap()
    {
        storage = new Dictionary<TKey,IList<TValue>>();
    }

    public void Add(TKey key, TValue value)
    {
        if (!storage.ContainsKey(key)) storage.Add(key, new List<TValue>());
        storage[key].Add(value);
    }

    public IEnumerable<TKey> Keys
    {
        get { return storage.Keys; }
    }

    public bool ContainsKey(TKey key)
    {
        return storage.ContainsKey(key);
    }

    public IList<TValue> this[TKey key]
    {
        get
        {
            if (!storage.ContainsKey(key))
                throw new KeyNotFoundException(
                    string.Format(
                        "The given key {0} was not found in the collection.", key));
            return storage[key];
        }
    }
}

关于如何使用它的简单示例:

const string key = "supported_encodings";
var map = new MultiMap<string,Encoding>();
map.Add(key, Encoding.ASCII);
map.Add(key, Encoding.UTF8);
map.Add(key, Encoding.Unicode);

foreach (var existingKey in map.Keys)
{
    var values = map[existingKey];
    Console.WriteLine(string.Join(",", values));
}