【问题标题】:Is there a more elegant way of adding an item to a Dictionary<> safely?有没有更优雅的方式将项目安全地添加到 Dictionary<> 中?
【发布时间】:2010-11-13 17:35:45
【问题描述】:

我需要将键/对象对添加到字典中,但我当然需要先检查键是否已存在,否则我会收到“字典中已存在键”错误。下面的代码解决了这个问题,但很笨重。

在不创建这样的字符串辅助方法的情况下,有什么更优雅的方法?

using System;
using System.Collections.Generic;

namespace TestDictStringObject
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, object> currentViews = new Dictionary<string, object>();

            StringHelpers.SafeDictionaryAdd(currentViews, "Customers", "view1");
            StringHelpers.SafeDictionaryAdd(currentViews, "Customers", "view2");
            StringHelpers.SafeDictionaryAdd(currentViews, "Employees", "view1");
            StringHelpers.SafeDictionaryAdd(currentViews, "Reports", "view1");

            foreach (KeyValuePair<string, object> pair in currentViews)
            {
                Console.WriteLine("{0} {1}", pair.Key, pair.Value);
            }
            Console.ReadLine();
        }
    }

    public static class StringHelpers
    {
        public static void SafeDictionaryAdd(Dictionary<string, object> dict, string key, object view)
        {
            if (!dict.ContainsKey(key))
            {
                dict.Add(key, view);
            }
            else
            {
                dict[key] = view;
            }
        }
    }
}

【问题讨论】:

    标签: c# collections dictionary


    【解决方案1】:

    只需使用索引器 - 如果它已经存在,它将覆盖,但它没有 首先存在:

    Dictionary<string, object> currentViews = new Dictionary<string, object>();
    currentViews["Customers"] = "view1";
    currentViews["Customers"] = "view2";
    currentViews["Employees"] = "view1";
    currentViews["Reports"] = "view1";
    

    如果键的存在表明存在错误(因此您希望它抛出),则基本上使用Add,否则使用索引器。 (这有点像强制转换和使用as 进行引用转换的区别。)

    如果您使用的是 C# 3 并且您有一组不同的键,您可以让这更加整洁:

    var currentViews = new Dictionary<string, object>()
    {
        { "Customers", "view2" },
        { "Employees", "view1" },
        { "Reports", "view1" },
    };
    

    这在你的情况下不起作用,因为集合初始化器总是使用Add,这将抛出第二个Customers条目。

    【讨论】:

    • 太好了,没有意识到简单的分配可以解决添加/覆盖问题,很好。
    【解决方案2】:

    怎么了……

    dict[key] = view;
    

    如果不存在,它会自动添加密钥。

    【讨论】:

    • 我认为值得注意的一点是,如果您存储的是 int,如果密钥不存在,dict[key] += amount 将不起作用
    【解决方案3】:

    简单

    dict[key] = view;
    

    来自 Dictionary.Item 的 MSDN 文档

    与 指定的键。如果指定的键是 未找到,get 操作会抛出 KeyNotFoundException 和一个 set 操作创建一个新元素 指定的键

    我的重点

    【讨论】:

      【解决方案4】:

      像往常一样,John Skeet 以闪电般的速度获得正确答案,但有趣的是,您也可以将 SafeAdd 编写为 IDictionary 上的扩展方法。

      public static void SafeAdd(this IDictionary<K, T>. dict, K key, T value)...
      

      【讨论】:

        【解决方案5】:

        虽然使用索引器显然是解决您的特定问题的正确答案,但为现有类型添加附加功能的问题的另一个更一般的答案是定义扩展方法。

        显然,这不是一个特别有用的示例,但在您下次发现真正需要时需要牢记:

        public static class DictionaryExtensions
        {
            public static void SafeAdd<TKey, TValue>(this Dictionary<TKey, TValue> dict, 
                                                     TKey key, TValue value)
            {
                dict[key] = value;
            }
        }
        

        【讨论】:

        • 我要提一下这只适用于 C# 3.0 及更高版本。
        猜你喜欢
        • 1970-01-01
        • 2011-06-13
        • 2018-02-23
        • 1970-01-01
        • 2021-10-29
        • 1970-01-01
        • 2011-04-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多