是否有更优雅的方式将项目安全地添加到Dictionary ?

时间:2021-12-24 07:36:39

I need to add key/object pairs to a dictionary, but I of course need to first check if the key already exists otherwise I get a "key already exists in dictionary" error. The code below solves this but is clunky.

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

What is a more elegant way of doing this without making a string helper method like this?

在没有像这样的字符串帮助方法的情况下,这样做更优雅的方法是什么?

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;
            }
        }
    }
}

5 个解决方案

#1


Just use the indexer - it will overwrite if it's already there, but it doesn't have to be there first:

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

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

Basically use Add if the existence of the key indicates a bug (so you want it to throw) and the indexer otherwise. (It's a bit like the difference between casting and using as for reference conversions.)

基本上使用Add如果密钥的存在指示错误(因此您希望它抛出),否则使用索引器。 (这有点像转换和使用之间的差异,参考转换。)

If you're using C# 3 and you have a distinct set of keys, you can make this even neater:

如果您使用的是C#3并且拥有一组独特的按键,则可以使其更加整洁:

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

That won't work in your case though, as collection initializers always use Add which will throw on the second Customers entry.

但是,这在你的情况下不起作用,因为集合初始值设定项总是使用Add,它会抛出第二个Customers条目。

#2


What's wrong with...

怎么了......

dict[key] = view;

It'll automatically add the key if it's non-existent.

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

#3


simply

dict[key] = view;

From the MSDN documentation of Dictionary.Item

从Dictionary.Item的MSDN文档

The value associated with the specified key. If the specified key is not found, a get operation throws a KeyNotFoundException, and a set operation creates a new element with the specified key.

与指定键关联的值。如果未找到指定的键,则get操作将引发KeyNotFoundException,并且set操作将使用指定的键创建新元素。

My emphasis

#4


As usual John Skeet gets in there with lighting speed with the right answer, but interestingly you could also have written your SafeAdd as an Extension Method on IDictionary.

像往常一样John Skeet带着合适的答案进入灯光速度,但有趣的是你也可以在IDictionary上编写SafeAdd作为扩展方法。

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

#5


Although using the indexer is clearly the right answer for your specific problem, another more general answer to the problem of adding additional functionality to an existing type would be to define an extension method.

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

Obviousy this isn't a particulary useful example, but something to bear in mind for the next time you find a real need:

显然,这不是一个特别有用的例子,但下次你发现真正需要时要记住:

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

#1


Just use the indexer - it will overwrite if it's already there, but it doesn't have to be there first:

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

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

Basically use Add if the existence of the key indicates a bug (so you want it to throw) and the indexer otherwise. (It's a bit like the difference between casting and using as for reference conversions.)

基本上使用Add如果密钥的存在指示错误(因此您希望它抛出),否则使用索引器。 (这有点像转换和使用之间的差异,参考转换。)

If you're using C# 3 and you have a distinct set of keys, you can make this even neater:

如果您使用的是C#3并且拥有一组独特的按键,则可以使其更加整洁:

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

That won't work in your case though, as collection initializers always use Add which will throw on the second Customers entry.

但是,这在你的情况下不起作用,因为集合初始值设定项总是使用Add,它会抛出第二个Customers条目。

#2


What's wrong with...

怎么了......

dict[key] = view;

It'll automatically add the key if it's non-existent.

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

#3


simply

dict[key] = view;

From the MSDN documentation of Dictionary.Item

从Dictionary.Item的MSDN文档

The value associated with the specified key. If the specified key is not found, a get operation throws a KeyNotFoundException, and a set operation creates a new element with the specified key.

与指定键关联的值。如果未找到指定的键,则get操作将引发KeyNotFoundException,并且set操作将使用指定的键创建新元素。

My emphasis

#4


As usual John Skeet gets in there with lighting speed with the right answer, but interestingly you could also have written your SafeAdd as an Extension Method on IDictionary.

像往常一样John Skeet带着合适的答案进入灯光速度,但有趣的是你也可以在IDictionary上编写SafeAdd作为扩展方法。

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

#5


Although using the indexer is clearly the right answer for your specific problem, another more general answer to the problem of adding additional functionality to an existing type would be to define an extension method.

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

Obviousy this isn't a particulary useful example, but something to bear in mind for the next time you find a real need:

显然,这不是一个特别有用的例子,但下次你发现真正需要时要记住:

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