【问题标题】:Argument Exception "Item with Same Key has already been added"参数异常“已添加具有相同键的项目”
【发布时间】:2014-12-18 10:56:55
【问题描述】:

我不断收到以下代码错误:

Dictionary<string, string> rct3Features = new Dictionary<string, string>();
Dictionary<string, string> rct4Features = new Dictionary<string, string>();

foreach (string line in rct3Lines) 
{
    string[] items = line.Split(new String[] { " " }, 2, StringSplitOptions.None);

    rct3Features.Add(items[0], items[1]);

    ////To print out the dictionary (to see if it works)
    //foreach (KeyValuePair<string, string> item in rct3Features)
    //{
    //    Console.WriteLine(item.Key + " " + item.Value);
    //}

}

错误抛出ArgumentException 说,

“已添加具有相同密钥的项目。”

经过多次 Google 搜索后,我不确定如何解决此问题。

稍后在代码中我需要访问字典以获得比较功能:

Compare4To3(rct4Features, rct3Features);

public static void Compare4To3(Dictionary<string, string> dictionaryOne, Dictionary<string, string> dictionaryTwo)
{
    //foreach (string item in dictionaryOne)
    //{

    //To print out the dictionary (to see if it works)
    foreach (KeyValuePair<string, string> item in dictionaryOne)
    {
        Console.WriteLine(item.Key + " " + item.Value);
    }

        //if (dictionaryTwo.ContainsKey(dictionaryOne.Keys)
        //{
        //    Console.Write("True");
        //}
        //else
        //{
        //    Console.Write("False");
        //}
    //}
}

此功能尚未完成,但我正在尝试解决此异常。有哪些方法可以修复此异常错误,并保持对字典的访问权限以与此功能一起使用?谢谢

【问题讨论】:

  • 停止尝试使用相同的键添加多个项目。也许您应该在添加时添加检查以确保密钥不存在。否则,我们无法知道正确的行动方案是什么,因为您几乎没有提供任何信息来说明如果存在重复项目,您希望发生什么。
  • 为什么会有重复的键?如果每个键需要多个值,则应使用Dictionary&lt;string, List&lt;string&gt;&gt;
  • 在下面查看我的答案以获取更多详细信息,但您可以用不同的语法替换您的 Add 。如果键已存在,则以下内容只会覆盖键的现有值:rct3Features[items[0]] = items[1];

标签: c# exception dictionary


【解决方案1】:

这个错误是不言自明的。字典键是唯一的,您不能拥有多个相同的键。要解决此问题,您应该像这样修改代码:

Dictionary<string, string> rct3Features = new Dictionary<string, string>();
Dictionary<string, string> rct4Features = new Dictionary<string, string>();

foreach (string line in rct3Lines) 
{
    string[] items = line.Split(new String[] { " " }, 2, StringSplitOptions.None);

    if (!rct3Features.ContainsKey(items[0]))
    {
        rct3Features.Add(items[0], items[1]);
    }

    ////To print out the dictionary (to see if it works)
    //foreach (KeyValuePair<string, string> item in rct3Features)
    //{
    //    Console.WriteLine(item.Key + " " + item.Value);
    //}
}

这个简单的if 语句可确保您仅在密钥 (items[0]) 不存在时尝试向字典中添加新条目。

【讨论】:

    【解决方案2】:

    为了说明您遇到的问题,让我们看一些代码...

    Dictionary<string, string> test = new Dictionary<string, string>();
    
    test.Add("Key1", "Value1");  // Works fine
    test.Add("Key2", "Value2");  // Works fine
    test.Add("Key1", "Value3");  // Fails because of duplicate key
    

    字典具有键/值对的原因是一个特性,所以你可以这样做......

    var myString = test["Key2"];  // myString is now Value2.
    

    如果 Dictionary 有 2 个 Key2,它不知道要返回哪一个,因此它会将您限制为唯一的键。

    【讨论】:

      【解决方案3】:

      当您尝试添加新键时,如果字典中已有键,则会引发该异常。

      rct3Lines 中的第一个单词必须不止一行。同一字典中不能有 2 个条目具有相同的键。

      如果密钥已经存在,您需要决定要发生的事情 - 如果您只想更新密钥存在的值,您可以简单地

      rct3Features[items[0]]=items[1]
      

      但是,如果没有,您可能需要测试密钥是否已经存在:

      if(rect3Features.ContainsKey(items[0]))
      {
          //Do something
      } 
      else 
      {
          //Do something else
      }
      

      【讨论】:

        【解决方案4】:

        正如其他人所说,您多次添加相同的密钥。如果这不是一个有效的方案,请检查 Jdinklage Morgoone 的答案(它只保存找到的键的第一个值),或者考虑这种解决方法(它只保存找到的键的最后一个值):

        // This will always overwrite the existing value if one is already stored for this key
        rct3Features[items[0]] = items[1];
        

        否则,如果单个键具有多个值是有效的,那么您应该考虑将您的值存储在一个 List&lt;string&gt; 中,用于每个 string 键。

        例如:

        var rct3Features = new Dictionary<string, List<string>>();
        var rct4Features = new Dictionary<string, List<string>>();
        
        foreach (string line in rct3Lines)
        {
            string[] items = line.Split(new String[] { " " }, 2, StringSplitOptions.None);
        
            if (!rct3Features.ContainsKey(items[0]))
            {
                // No items for this key have been added, so create a new list
                // for the value with item[1] as the only item in the list
                rct3Features.Add(items[0], new List<string> { items[1] });
            }
            else
            {
                // This key already exists, so add item[1] to the existing list value
                rct3Features[items[0]].Add(items[1]);
            }
        }
        
        // To display your keys and values (testing)
        foreach (KeyValuePair<string, List<string>> item in rct3Features)
        {
            Console.WriteLine("The Key: {0} has values:", item.Key);
            foreach (string value in item.Value)
            {
                Console.WriteLine(" - {0}", value);
            }
        }
        

        【讨论】:

          【解决方案5】:

          在向其添加任何项目之前清除字典。我不知道一个对象的字典在分配期间如何影响另一个对象,但是在创建另一个具有相同键值对的对象后出现错误。

          注意: 如果您要在循环中添加项目,请确保在进入循环之前清除字典。

          【讨论】:

          • new Dictionary&lt;T, U&gt;()returns an empty dictionary,所以不需要在构建后清除。在每次调用 Add 之前清除它停止异常,但会导致字典中只出现最后一项。你确定这是个好建议吗?
          【解决方案6】:

          如果您想要“插入或替换”语义,请使用以下语法:

          A[key] = value;     // <-- insert or replace semantics
          

          它比在“Add()”之前涉及“ContainsKey()”或“Remove()”的调用更高效、更易读。

          所以在你的情况下:

          rct3Features[items[0]] = items[1];
          

          【讨论】:

            猜你喜欢
            • 2011-06-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多