什么是 C# 中允许重复键的字典的替代方案

本文关键字:字典 方案 许重复 什么 | 更新日期: 2023-09-27 18:34:13

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

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

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

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

什么是 C# 中允许重复键的字典的替代方案

在您的情况下,同一个键与多个值相关,因此标准字典不合适。您可以像Dictionary<Key, List<Values>>一样声明它.

但是,您也可以使用:

查找类,即

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

为此,您需要框架 3.5 及更多。

您需要的是

Project与一个或多个技术人员之间的关系:

public class Project
{
    public ICollection<Technician> Technicians { get; set; }
}
var project = new Project();
project.Technicians = new List<Technician>()
{
    new Technician(),
    new Technician()
};

您的对象应该反映现实生活中的关系。

作为旁注,您可能有兴趣阅读有关域驱动设计的信息。

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;
}
<</div> div class="answers">

有一个来自 MS 的实验性 NuGet 包,其中包含 MultiValueDictionary

基本上,它就像 Dictionary<Project, List<Technicians>> ,除了您不必在每次访问它时重复所有逻辑来管理List

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

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

我已经从这篇文章中复制粘贴了我自己的答案。

很容易"滚动自己的"字典版本,允许"重复键"条目。这是一个粗略的简单实现。您可能需要考虑在 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));
}