DuplicateDictionary - A dictionary-like class which allows duplicates












5












$begingroup$


Since I couldn't find any good answers I made my own class called DuplicateDictionary for personal usage. I would like some tips to improve it.



public class DuplicateDictionary<TKey, TValue>: List<KeyValuePair<TKey, TValue>>
{
public DuplicateDictionary()
{

}

public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
foreach(KeyValuePair<TKey, TValue> kvp in list)
{
this.Add(kvp);
}
}

public DuplicateDictionary(Dictionary<TKey, TValue> dictionary)
{
foreach(KeyValuePair<TKey, TValue> kvp in dictionary)
{
this.Add(kvp);
}
}

public TValue this[TKey index]
{
get
{
this.ContainsKey(index);
return this[index];
}
set
{
this[index] = value;
}
}

public void Add(TKey key, TValue value)
{
this.Add(new KeyValuePair<TKey, TValue>(key, value));
}

public bool ContainsKey(TKey key)
{
foreach(KeyValuePair<TKey, TValue> kvp in this)
if(kvp.Key.Equals(key)) return true;

return false;
}
}


This class is useful for log things. I use it to log a calculator's past functions and numbers, and once equals is pressed, adds all the past numbers with the functions.










share|improve this question











$endgroup$








  • 7




    $begingroup$
    I think you should provide an example on how some1 is supposed to use this class. How are you going to access duplicate values? If you can't then why store them? Also your indexer looks really fishy.
    $endgroup$
    – Nikita B
    Aug 27 '15 at 7:02












  • $begingroup$
    Refer to the edit
    $endgroup$
    – hexagonest
    Aug 28 '15 at 3:49
















5












$begingroup$


Since I couldn't find any good answers I made my own class called DuplicateDictionary for personal usage. I would like some tips to improve it.



public class DuplicateDictionary<TKey, TValue>: List<KeyValuePair<TKey, TValue>>
{
public DuplicateDictionary()
{

}

public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
foreach(KeyValuePair<TKey, TValue> kvp in list)
{
this.Add(kvp);
}
}

public DuplicateDictionary(Dictionary<TKey, TValue> dictionary)
{
foreach(KeyValuePair<TKey, TValue> kvp in dictionary)
{
this.Add(kvp);
}
}

public TValue this[TKey index]
{
get
{
this.ContainsKey(index);
return this[index];
}
set
{
this[index] = value;
}
}

public void Add(TKey key, TValue value)
{
this.Add(new KeyValuePair<TKey, TValue>(key, value));
}

public bool ContainsKey(TKey key)
{
foreach(KeyValuePair<TKey, TValue> kvp in this)
if(kvp.Key.Equals(key)) return true;

return false;
}
}


This class is useful for log things. I use it to log a calculator's past functions and numbers, and once equals is pressed, adds all the past numbers with the functions.










share|improve this question











$endgroup$








  • 7




    $begingroup$
    I think you should provide an example on how some1 is supposed to use this class. How are you going to access duplicate values? If you can't then why store them? Also your indexer looks really fishy.
    $endgroup$
    – Nikita B
    Aug 27 '15 at 7:02












  • $begingroup$
    Refer to the edit
    $endgroup$
    – hexagonest
    Aug 28 '15 at 3:49














5












5








5


0



$begingroup$


Since I couldn't find any good answers I made my own class called DuplicateDictionary for personal usage. I would like some tips to improve it.



public class DuplicateDictionary<TKey, TValue>: List<KeyValuePair<TKey, TValue>>
{
public DuplicateDictionary()
{

}

public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
foreach(KeyValuePair<TKey, TValue> kvp in list)
{
this.Add(kvp);
}
}

public DuplicateDictionary(Dictionary<TKey, TValue> dictionary)
{
foreach(KeyValuePair<TKey, TValue> kvp in dictionary)
{
this.Add(kvp);
}
}

public TValue this[TKey index]
{
get
{
this.ContainsKey(index);
return this[index];
}
set
{
this[index] = value;
}
}

public void Add(TKey key, TValue value)
{
this.Add(new KeyValuePair<TKey, TValue>(key, value));
}

public bool ContainsKey(TKey key)
{
foreach(KeyValuePair<TKey, TValue> kvp in this)
if(kvp.Key.Equals(key)) return true;

return false;
}
}


This class is useful for log things. I use it to log a calculator's past functions and numbers, and once equals is pressed, adds all the past numbers with the functions.










share|improve this question











$endgroup$




Since I couldn't find any good answers I made my own class called DuplicateDictionary for personal usage. I would like some tips to improve it.



public class DuplicateDictionary<TKey, TValue>: List<KeyValuePair<TKey, TValue>>
{
public DuplicateDictionary()
{

}

public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
foreach(KeyValuePair<TKey, TValue> kvp in list)
{
this.Add(kvp);
}
}

public DuplicateDictionary(Dictionary<TKey, TValue> dictionary)
{
foreach(KeyValuePair<TKey, TValue> kvp in dictionary)
{
this.Add(kvp);
}
}

public TValue this[TKey index]
{
get
{
this.ContainsKey(index);
return this[index];
}
set
{
this[index] = value;
}
}

public void Add(TKey key, TValue value)
{
this.Add(new KeyValuePair<TKey, TValue>(key, value));
}

public bool ContainsKey(TKey key)
{
foreach(KeyValuePair<TKey, TValue> kvp in this)
if(kvp.Key.Equals(key)) return true;

return false;
}
}


This class is useful for log things. I use it to log a calculator's past functions and numbers, and once equals is pressed, adds all the past numbers with the functions.







c# dictionary






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Aug 28 '15 at 3:47







hexagonest

















asked Aug 27 '15 at 4:34









hexagonesthexagonest

15327




15327








  • 7




    $begingroup$
    I think you should provide an example on how some1 is supposed to use this class. How are you going to access duplicate values? If you can't then why store them? Also your indexer looks really fishy.
    $endgroup$
    – Nikita B
    Aug 27 '15 at 7:02












  • $begingroup$
    Refer to the edit
    $endgroup$
    – hexagonest
    Aug 28 '15 at 3:49














  • 7




    $begingroup$
    I think you should provide an example on how some1 is supposed to use this class. How are you going to access duplicate values? If you can't then why store them? Also your indexer looks really fishy.
    $endgroup$
    – Nikita B
    Aug 27 '15 at 7:02












  • $begingroup$
    Refer to the edit
    $endgroup$
    – hexagonest
    Aug 28 '15 at 3:49








7




7




$begingroup$
I think you should provide an example on how some1 is supposed to use this class. How are you going to access duplicate values? If you can't then why store them? Also your indexer looks really fishy.
$endgroup$
– Nikita B
Aug 27 '15 at 7:02






$begingroup$
I think you should provide an example on how some1 is supposed to use this class. How are you going to access duplicate values? If you can't then why store them? Also your indexer looks really fishy.
$endgroup$
– Nikita B
Aug 27 '15 at 7:02














$begingroup$
Refer to the edit
$endgroup$
– hexagonest
Aug 28 '15 at 3:49




$begingroup$
Refer to the edit
$endgroup$
– hexagonest
Aug 28 '15 at 3:49










5 Answers
5






active

oldest

votes


















14












$begingroup$

Such a data structure already exists, and is called ILookup<TKey, TElement>. It can be created using the ToLookup extension.




The ToLookup<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>) method returns a Lookup<TKey, TElement>, a one-to-many dictionary that maps keys to collections of values. A Lookup<TKey, TElement> differs from a Dictionary<TKey, TValue>, which performs a one-to-one mapping of keys to single values.




var list = new List<Tuple<string, int>>
{
Tuple.Create("a", 1),
Tuple.Create("a", 2),
Tuple.Create("a", 3),
Tuple.Create("b", 4),
Tuple.Create("c", 5)
};

var lookup = list.ToLookup(t => t.Item1, t => t.Item2);

foreach(var kv in lookup)
{
Console.Write(kv.Key);
Console.WriteLine(" - " + string.Join(", ", kv));
}

// prints
// a - 1, 2, 3
// b - 4
// c - 5


As Vince pointed out, your DuplicateDictionary will suffer from slow access. Lookup won't.






share|improve this answer









$endgroup$





















    11












    $begingroup$

    First I second what Vince Panuccio stated in his answer




    I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary or with a set or list as its value.






    Bug alert



    This will break with an StackOverflowException




    public TValue this[TKey index]
    {
    get
    {
    this.ContainsKey(index);
    return this[index];
    }
    set
    {
    this[index] = value;
    }
    }



    by calling this.ContainsKey() which again refers to the Item (this[TKey]) property and if we would omit this call, it would just break again with a StackOverflowException based on the return this[index]; which is reffering the property getter itself again.



    Setting aside this big bug, an argument named index usually indicates some kind of numerical type. So a better parameter name would be in this case just key.





    The ctor




    public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
    {
    foreach(KeyValuePair<TKey, TValue> kvp in list)
    {
    this.Add(kvp);
    }
    }



    could be easily improved by using the AddRange() method of the List<T> like so



    public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
    {
    this.AddRange(list);
    }


    but that isn't really needed in this way because you also have a ctor which takes an Dictionary<TKey, TValue> as a parameter. I suggest to replace both ctors by a different one which only takes an IEnumerable<KeyValuePair<TKey, TValue>> like so



    public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
    {
    this.AddRange(items);
    }


    which can be called using a Dictionary and a List.



    This looks good but we can still do better by using the ctor of the List instead like so



    public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
    : base(items)
    { }





    share|improve this answer











    $endgroup$













    • $begingroup$
      What does base do? Excuse my ignorance
      $endgroup$
      – hexagonest
      Aug 27 '15 at 9:11










    • $begingroup$
      Thats the calling of the ctor of the inherited class
      $endgroup$
      – Heslacher
      Aug 27 '15 at 9:12



















    6












    $begingroup$

    It might help if you explain the problem you are trying to solve first, but I'll have a crack at this.



    I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary with a set or list as its value.



    What you have is a list of KeyValuePairs which is not the same as a Dictionary :-)



    Dictionaries benefit from having unique keys by giving you fast lookups, I'm not sure what benefit you gain by having a DuplicateDictionary.






    share|improve this answer











    $endgroup$





















      1












      $begingroup$

      I think you want to have some kind of a multi value single key dictionary. So I suggest to use for example a List<> to hold the values.



      Here's an example:



      public class DuplicateDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
      {
      public new IEnumerable<KeyValuePair<TKey, TValue>> this[TKey key]
      {
      get
      {
      List<TValue> values;
      if (!TryGetValue(key, out values))
      {
      return Enumerable.Empty<KeyValuePair<TKey, TValue>>();
      }

      return values.Select(v => new KeyValuePair<TKey, TValue>(key, v));
      }
      set
      {
      foreach (var _value in value.Select(kvp => kvp.Value))
      {
      Add(key, _value);
      }
      }
      }



      public void Add(TKey key, TValue value)
      {
      List<TValue> values;
      if (!TryGetValue(key, out values))
      {
      values = new List<TValue>();
      Add(key, values);
      }
      values.Add(value);
      }

      public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
      {
      foreach (var item in ((Dictionary<TKey, List<TValue>>)this))
      {
      foreach (var value in item.Value)
      {
      yield return new KeyValuePair<TKey, TValue>(item.Key, value);
      }
      }
      }
      }




      static void Main(string args)
      {
      var dupDic = new DuplicateDictionary<string, string>();

      dupDic.Add("abc", "123");
      dupDic.Add("abc", "456");
      dupDic.Add("xyz", "789");
      dupDic.Add("xyz", "098");
      dupDic.Add("xyz", "290");

      foreach (var kvp in dupDic)
      {
      Console.WriteLine("Key = "{0}" Value = "{1}"", kvp.Key, kvp.Value);
      }

      Console.ReadKey();
      }





      share|improve this answer











      $endgroup$





















        0












        $begingroup$

        You can List of KeyValuePair to store duplicates



        Example :



        List< KeyValuePair < string, string>> listKeyValPair= new List< KeyValuePair< string, string>>();



        KeyValuePair< string, string> keyValue= new KeyValuePair< string, string>("KEY1", "VALUE1");



        listKeyValPair.Add(keyValue);





        share








        New contributor




        Nagesh Hugar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.






        $endgroup$













          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f102026%2fduplicatedictionary-a-dictionary-like-class-which-allows-duplicates%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          5 Answers
          5






          active

          oldest

          votes








          5 Answers
          5






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          14












          $begingroup$

          Such a data structure already exists, and is called ILookup<TKey, TElement>. It can be created using the ToLookup extension.




          The ToLookup<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>) method returns a Lookup<TKey, TElement>, a one-to-many dictionary that maps keys to collections of values. A Lookup<TKey, TElement> differs from a Dictionary<TKey, TValue>, which performs a one-to-one mapping of keys to single values.




          var list = new List<Tuple<string, int>>
          {
          Tuple.Create("a", 1),
          Tuple.Create("a", 2),
          Tuple.Create("a", 3),
          Tuple.Create("b", 4),
          Tuple.Create("c", 5)
          };

          var lookup = list.ToLookup(t => t.Item1, t => t.Item2);

          foreach(var kv in lookup)
          {
          Console.Write(kv.Key);
          Console.WriteLine(" - " + string.Join(", ", kv));
          }

          // prints
          // a - 1, 2, 3
          // b - 4
          // c - 5


          As Vince pointed out, your DuplicateDictionary will suffer from slow access. Lookup won't.






          share|improve this answer









          $endgroup$


















            14












            $begingroup$

            Such a data structure already exists, and is called ILookup<TKey, TElement>. It can be created using the ToLookup extension.




            The ToLookup<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>) method returns a Lookup<TKey, TElement>, a one-to-many dictionary that maps keys to collections of values. A Lookup<TKey, TElement> differs from a Dictionary<TKey, TValue>, which performs a one-to-one mapping of keys to single values.




            var list = new List<Tuple<string, int>>
            {
            Tuple.Create("a", 1),
            Tuple.Create("a", 2),
            Tuple.Create("a", 3),
            Tuple.Create("b", 4),
            Tuple.Create("c", 5)
            };

            var lookup = list.ToLookup(t => t.Item1, t => t.Item2);

            foreach(var kv in lookup)
            {
            Console.Write(kv.Key);
            Console.WriteLine(" - " + string.Join(", ", kv));
            }

            // prints
            // a - 1, 2, 3
            // b - 4
            // c - 5


            As Vince pointed out, your DuplicateDictionary will suffer from slow access. Lookup won't.






            share|improve this answer









            $endgroup$
















              14












              14








              14





              $begingroup$

              Such a data structure already exists, and is called ILookup<TKey, TElement>. It can be created using the ToLookup extension.




              The ToLookup<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>) method returns a Lookup<TKey, TElement>, a one-to-many dictionary that maps keys to collections of values. A Lookup<TKey, TElement> differs from a Dictionary<TKey, TValue>, which performs a one-to-one mapping of keys to single values.




              var list = new List<Tuple<string, int>>
              {
              Tuple.Create("a", 1),
              Tuple.Create("a", 2),
              Tuple.Create("a", 3),
              Tuple.Create("b", 4),
              Tuple.Create("c", 5)
              };

              var lookup = list.ToLookup(t => t.Item1, t => t.Item2);

              foreach(var kv in lookup)
              {
              Console.Write(kv.Key);
              Console.WriteLine(" - " + string.Join(", ", kv));
              }

              // prints
              // a - 1, 2, 3
              // b - 4
              // c - 5


              As Vince pointed out, your DuplicateDictionary will suffer from slow access. Lookup won't.






              share|improve this answer









              $endgroup$



              Such a data structure already exists, and is called ILookup<TKey, TElement>. It can be created using the ToLookup extension.




              The ToLookup<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>) method returns a Lookup<TKey, TElement>, a one-to-many dictionary that maps keys to collections of values. A Lookup<TKey, TElement> differs from a Dictionary<TKey, TValue>, which performs a one-to-one mapping of keys to single values.




              var list = new List<Tuple<string, int>>
              {
              Tuple.Create("a", 1),
              Tuple.Create("a", 2),
              Tuple.Create("a", 3),
              Tuple.Create("b", 4),
              Tuple.Create("c", 5)
              };

              var lookup = list.ToLookup(t => t.Item1, t => t.Item2);

              foreach(var kv in lookup)
              {
              Console.Write(kv.Key);
              Console.WriteLine(" - " + string.Join(", ", kv));
              }

              // prints
              // a - 1, 2, 3
              // b - 4
              // c - 5


              As Vince pointed out, your DuplicateDictionary will suffer from slow access. Lookup won't.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Aug 27 '15 at 9:04









              dcastrodcastro

              1,057713




              1,057713

























                  11












                  $begingroup$

                  First I second what Vince Panuccio stated in his answer




                  I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary or with a set or list as its value.






                  Bug alert



                  This will break with an StackOverflowException




                  public TValue this[TKey index]
                  {
                  get
                  {
                  this.ContainsKey(index);
                  return this[index];
                  }
                  set
                  {
                  this[index] = value;
                  }
                  }



                  by calling this.ContainsKey() which again refers to the Item (this[TKey]) property and if we would omit this call, it would just break again with a StackOverflowException based on the return this[index]; which is reffering the property getter itself again.



                  Setting aside this big bug, an argument named index usually indicates some kind of numerical type. So a better parameter name would be in this case just key.





                  The ctor




                  public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
                  {
                  foreach(KeyValuePair<TKey, TValue> kvp in list)
                  {
                  this.Add(kvp);
                  }
                  }



                  could be easily improved by using the AddRange() method of the List<T> like so



                  public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
                  {
                  this.AddRange(list);
                  }


                  but that isn't really needed in this way because you also have a ctor which takes an Dictionary<TKey, TValue> as a parameter. I suggest to replace both ctors by a different one which only takes an IEnumerable<KeyValuePair<TKey, TValue>> like so



                  public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
                  {
                  this.AddRange(items);
                  }


                  which can be called using a Dictionary and a List.



                  This looks good but we can still do better by using the ctor of the List instead like so



                  public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
                  : base(items)
                  { }





                  share|improve this answer











                  $endgroup$













                  • $begingroup$
                    What does base do? Excuse my ignorance
                    $endgroup$
                    – hexagonest
                    Aug 27 '15 at 9:11










                  • $begingroup$
                    Thats the calling of the ctor of the inherited class
                    $endgroup$
                    – Heslacher
                    Aug 27 '15 at 9:12
















                  11












                  $begingroup$

                  First I second what Vince Panuccio stated in his answer




                  I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary or with a set or list as its value.






                  Bug alert



                  This will break with an StackOverflowException




                  public TValue this[TKey index]
                  {
                  get
                  {
                  this.ContainsKey(index);
                  return this[index];
                  }
                  set
                  {
                  this[index] = value;
                  }
                  }



                  by calling this.ContainsKey() which again refers to the Item (this[TKey]) property and if we would omit this call, it would just break again with a StackOverflowException based on the return this[index]; which is reffering the property getter itself again.



                  Setting aside this big bug, an argument named index usually indicates some kind of numerical type. So a better parameter name would be in this case just key.





                  The ctor




                  public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
                  {
                  foreach(KeyValuePair<TKey, TValue> kvp in list)
                  {
                  this.Add(kvp);
                  }
                  }



                  could be easily improved by using the AddRange() method of the List<T> like so



                  public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
                  {
                  this.AddRange(list);
                  }


                  but that isn't really needed in this way because you also have a ctor which takes an Dictionary<TKey, TValue> as a parameter. I suggest to replace both ctors by a different one which only takes an IEnumerable<KeyValuePair<TKey, TValue>> like so



                  public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
                  {
                  this.AddRange(items);
                  }


                  which can be called using a Dictionary and a List.



                  This looks good but we can still do better by using the ctor of the List instead like so



                  public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
                  : base(items)
                  { }





                  share|improve this answer











                  $endgroup$













                  • $begingroup$
                    What does base do? Excuse my ignorance
                    $endgroup$
                    – hexagonest
                    Aug 27 '15 at 9:11










                  • $begingroup$
                    Thats the calling of the ctor of the inherited class
                    $endgroup$
                    – Heslacher
                    Aug 27 '15 at 9:12














                  11












                  11








                  11





                  $begingroup$

                  First I second what Vince Panuccio stated in his answer




                  I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary or with a set or list as its value.






                  Bug alert



                  This will break with an StackOverflowException




                  public TValue this[TKey index]
                  {
                  get
                  {
                  this.ContainsKey(index);
                  return this[index];
                  }
                  set
                  {
                  this[index] = value;
                  }
                  }



                  by calling this.ContainsKey() which again refers to the Item (this[TKey]) property and if we would omit this call, it would just break again with a StackOverflowException based on the return this[index]; which is reffering the property getter itself again.



                  Setting aside this big bug, an argument named index usually indicates some kind of numerical type. So a better parameter name would be in this case just key.





                  The ctor




                  public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
                  {
                  foreach(KeyValuePair<TKey, TValue> kvp in list)
                  {
                  this.Add(kvp);
                  }
                  }



                  could be easily improved by using the AddRange() method of the List<T> like so



                  public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
                  {
                  this.AddRange(list);
                  }


                  but that isn't really needed in this way because you also have a ctor which takes an Dictionary<TKey, TValue> as a parameter. I suggest to replace both ctors by a different one which only takes an IEnumerable<KeyValuePair<TKey, TValue>> like so



                  public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
                  {
                  this.AddRange(items);
                  }


                  which can be called using a Dictionary and a List.



                  This looks good but we can still do better by using the ctor of the List instead like so



                  public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
                  : base(items)
                  { }





                  share|improve this answer











                  $endgroup$



                  First I second what Vince Panuccio stated in his answer




                  I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary or with a set or list as its value.






                  Bug alert



                  This will break with an StackOverflowException




                  public TValue this[TKey index]
                  {
                  get
                  {
                  this.ContainsKey(index);
                  return this[index];
                  }
                  set
                  {
                  this[index] = value;
                  }
                  }



                  by calling this.ContainsKey() which again refers to the Item (this[TKey]) property and if we would omit this call, it would just break again with a StackOverflowException based on the return this[index]; which is reffering the property getter itself again.



                  Setting aside this big bug, an argument named index usually indicates some kind of numerical type. So a better parameter name would be in this case just key.





                  The ctor




                  public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
                  {
                  foreach(KeyValuePair<TKey, TValue> kvp in list)
                  {
                  this.Add(kvp);
                  }
                  }



                  could be easily improved by using the AddRange() method of the List<T> like so



                  public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
                  {
                  this.AddRange(list);
                  }


                  but that isn't really needed in this way because you also have a ctor which takes an Dictionary<TKey, TValue> as a parameter. I suggest to replace both ctors by a different one which only takes an IEnumerable<KeyValuePair<TKey, TValue>> like so



                  public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
                  {
                  this.AddRange(items);
                  }


                  which can be called using a Dictionary and a List.



                  This looks good but we can still do better by using the ctor of the List instead like so



                  public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
                  : base(items)
                  { }






                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Apr 13 '17 at 12:40









                  Community

                  1




                  1










                  answered Aug 27 '15 at 4:59









                  HeslacherHeslacher

                  45.1k462158




                  45.1k462158












                  • $begingroup$
                    What does base do? Excuse my ignorance
                    $endgroup$
                    – hexagonest
                    Aug 27 '15 at 9:11










                  • $begingroup$
                    Thats the calling of the ctor of the inherited class
                    $endgroup$
                    – Heslacher
                    Aug 27 '15 at 9:12


















                  • $begingroup$
                    What does base do? Excuse my ignorance
                    $endgroup$
                    – hexagonest
                    Aug 27 '15 at 9:11










                  • $begingroup$
                    Thats the calling of the ctor of the inherited class
                    $endgroup$
                    – Heslacher
                    Aug 27 '15 at 9:12
















                  $begingroup$
                  What does base do? Excuse my ignorance
                  $endgroup$
                  – hexagonest
                  Aug 27 '15 at 9:11




                  $begingroup$
                  What does base do? Excuse my ignorance
                  $endgroup$
                  – hexagonest
                  Aug 27 '15 at 9:11












                  $begingroup$
                  Thats the calling of the ctor of the inherited class
                  $endgroup$
                  – Heslacher
                  Aug 27 '15 at 9:12




                  $begingroup$
                  Thats the calling of the ctor of the inherited class
                  $endgroup$
                  – Heslacher
                  Aug 27 '15 at 9:12











                  6












                  $begingroup$

                  It might help if you explain the problem you are trying to solve first, but I'll have a crack at this.



                  I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary with a set or list as its value.



                  What you have is a list of KeyValuePairs which is not the same as a Dictionary :-)



                  Dictionaries benefit from having unique keys by giving you fast lookups, I'm not sure what benefit you gain by having a DuplicateDictionary.






                  share|improve this answer











                  $endgroup$


















                    6












                    $begingroup$

                    It might help if you explain the problem you are trying to solve first, but I'll have a crack at this.



                    I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary with a set or list as its value.



                    What you have is a list of KeyValuePairs which is not the same as a Dictionary :-)



                    Dictionaries benefit from having unique keys by giving you fast lookups, I'm not sure what benefit you gain by having a DuplicateDictionary.






                    share|improve this answer











                    $endgroup$
















                      6












                      6








                      6





                      $begingroup$

                      It might help if you explain the problem you are trying to solve first, but I'll have a crack at this.



                      I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary with a set or list as its value.



                      What you have is a list of KeyValuePairs which is not the same as a Dictionary :-)



                      Dictionaries benefit from having unique keys by giving you fast lookups, I'm not sure what benefit you gain by having a DuplicateDictionary.






                      share|improve this answer











                      $endgroup$



                      It might help if you explain the problem you are trying to solve first, but I'll have a crack at this.



                      I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary with a set or list as its value.



                      What you have is a list of KeyValuePairs which is not the same as a Dictionary :-)



                      Dictionaries benefit from having unique keys by giving you fast lookups, I'm not sure what benefit you gain by having a DuplicateDictionary.







                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Aug 28 '15 at 10:36

























                      answered Aug 27 '15 at 4:44









                      Vince PanuccioVince Panuccio

                      33015




                      33015























                          1












                          $begingroup$

                          I think you want to have some kind of a multi value single key dictionary. So I suggest to use for example a List<> to hold the values.



                          Here's an example:



                          public class DuplicateDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
                          {
                          public new IEnumerable<KeyValuePair<TKey, TValue>> this[TKey key]
                          {
                          get
                          {
                          List<TValue> values;
                          if (!TryGetValue(key, out values))
                          {
                          return Enumerable.Empty<KeyValuePair<TKey, TValue>>();
                          }

                          return values.Select(v => new KeyValuePair<TKey, TValue>(key, v));
                          }
                          set
                          {
                          foreach (var _value in value.Select(kvp => kvp.Value))
                          {
                          Add(key, _value);
                          }
                          }
                          }



                          public void Add(TKey key, TValue value)
                          {
                          List<TValue> values;
                          if (!TryGetValue(key, out values))
                          {
                          values = new List<TValue>();
                          Add(key, values);
                          }
                          values.Add(value);
                          }

                          public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
                          {
                          foreach (var item in ((Dictionary<TKey, List<TValue>>)this))
                          {
                          foreach (var value in item.Value)
                          {
                          yield return new KeyValuePair<TKey, TValue>(item.Key, value);
                          }
                          }
                          }
                          }




                          static void Main(string args)
                          {
                          var dupDic = new DuplicateDictionary<string, string>();

                          dupDic.Add("abc", "123");
                          dupDic.Add("abc", "456");
                          dupDic.Add("xyz", "789");
                          dupDic.Add("xyz", "098");
                          dupDic.Add("xyz", "290");

                          foreach (var kvp in dupDic)
                          {
                          Console.WriteLine("Key = "{0}" Value = "{1}"", kvp.Key, kvp.Value);
                          }

                          Console.ReadKey();
                          }





                          share|improve this answer











                          $endgroup$


















                            1












                            $begingroup$

                            I think you want to have some kind of a multi value single key dictionary. So I suggest to use for example a List<> to hold the values.



                            Here's an example:



                            public class DuplicateDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
                            {
                            public new IEnumerable<KeyValuePair<TKey, TValue>> this[TKey key]
                            {
                            get
                            {
                            List<TValue> values;
                            if (!TryGetValue(key, out values))
                            {
                            return Enumerable.Empty<KeyValuePair<TKey, TValue>>();
                            }

                            return values.Select(v => new KeyValuePair<TKey, TValue>(key, v));
                            }
                            set
                            {
                            foreach (var _value in value.Select(kvp => kvp.Value))
                            {
                            Add(key, _value);
                            }
                            }
                            }



                            public void Add(TKey key, TValue value)
                            {
                            List<TValue> values;
                            if (!TryGetValue(key, out values))
                            {
                            values = new List<TValue>();
                            Add(key, values);
                            }
                            values.Add(value);
                            }

                            public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
                            {
                            foreach (var item in ((Dictionary<TKey, List<TValue>>)this))
                            {
                            foreach (var value in item.Value)
                            {
                            yield return new KeyValuePair<TKey, TValue>(item.Key, value);
                            }
                            }
                            }
                            }




                            static void Main(string args)
                            {
                            var dupDic = new DuplicateDictionary<string, string>();

                            dupDic.Add("abc", "123");
                            dupDic.Add("abc", "456");
                            dupDic.Add("xyz", "789");
                            dupDic.Add("xyz", "098");
                            dupDic.Add("xyz", "290");

                            foreach (var kvp in dupDic)
                            {
                            Console.WriteLine("Key = "{0}" Value = "{1}"", kvp.Key, kvp.Value);
                            }

                            Console.ReadKey();
                            }





                            share|improve this answer











                            $endgroup$
















                              1












                              1








                              1





                              $begingroup$

                              I think you want to have some kind of a multi value single key dictionary. So I suggest to use for example a List<> to hold the values.



                              Here's an example:



                              public class DuplicateDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
                              {
                              public new IEnumerable<KeyValuePair<TKey, TValue>> this[TKey key]
                              {
                              get
                              {
                              List<TValue> values;
                              if (!TryGetValue(key, out values))
                              {
                              return Enumerable.Empty<KeyValuePair<TKey, TValue>>();
                              }

                              return values.Select(v => new KeyValuePair<TKey, TValue>(key, v));
                              }
                              set
                              {
                              foreach (var _value in value.Select(kvp => kvp.Value))
                              {
                              Add(key, _value);
                              }
                              }
                              }



                              public void Add(TKey key, TValue value)
                              {
                              List<TValue> values;
                              if (!TryGetValue(key, out values))
                              {
                              values = new List<TValue>();
                              Add(key, values);
                              }
                              values.Add(value);
                              }

                              public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
                              {
                              foreach (var item in ((Dictionary<TKey, List<TValue>>)this))
                              {
                              foreach (var value in item.Value)
                              {
                              yield return new KeyValuePair<TKey, TValue>(item.Key, value);
                              }
                              }
                              }
                              }




                              static void Main(string args)
                              {
                              var dupDic = new DuplicateDictionary<string, string>();

                              dupDic.Add("abc", "123");
                              dupDic.Add("abc", "456");
                              dupDic.Add("xyz", "789");
                              dupDic.Add("xyz", "098");
                              dupDic.Add("xyz", "290");

                              foreach (var kvp in dupDic)
                              {
                              Console.WriteLine("Key = "{0}" Value = "{1}"", kvp.Key, kvp.Value);
                              }

                              Console.ReadKey();
                              }





                              share|improve this answer











                              $endgroup$



                              I think you want to have some kind of a multi value single key dictionary. So I suggest to use for example a List<> to hold the values.



                              Here's an example:



                              public class DuplicateDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
                              {
                              public new IEnumerable<KeyValuePair<TKey, TValue>> this[TKey key]
                              {
                              get
                              {
                              List<TValue> values;
                              if (!TryGetValue(key, out values))
                              {
                              return Enumerable.Empty<KeyValuePair<TKey, TValue>>();
                              }

                              return values.Select(v => new KeyValuePair<TKey, TValue>(key, v));
                              }
                              set
                              {
                              foreach (var _value in value.Select(kvp => kvp.Value))
                              {
                              Add(key, _value);
                              }
                              }
                              }



                              public void Add(TKey key, TValue value)
                              {
                              List<TValue> values;
                              if (!TryGetValue(key, out values))
                              {
                              values = new List<TValue>();
                              Add(key, values);
                              }
                              values.Add(value);
                              }

                              public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
                              {
                              foreach (var item in ((Dictionary<TKey, List<TValue>>)this))
                              {
                              foreach (var value in item.Value)
                              {
                              yield return new KeyValuePair<TKey, TValue>(item.Key, value);
                              }
                              }
                              }
                              }




                              static void Main(string args)
                              {
                              var dupDic = new DuplicateDictionary<string, string>();

                              dupDic.Add("abc", "123");
                              dupDic.Add("abc", "456");
                              dupDic.Add("xyz", "789");
                              dupDic.Add("xyz", "098");
                              dupDic.Add("xyz", "290");

                              foreach (var kvp in dupDic)
                              {
                              Console.WriteLine("Key = "{0}" Value = "{1}"", kvp.Key, kvp.Value);
                              }

                              Console.ReadKey();
                              }






                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              edited Aug 27 '15 at 19:26

























                              answered Aug 27 '15 at 18:52









                              t3chb0tt3chb0t

                              34.7k750121




                              34.7k750121























                                  0












                                  $begingroup$

                                  You can List of KeyValuePair to store duplicates



                                  Example :



                                  List< KeyValuePair < string, string>> listKeyValPair= new List< KeyValuePair< string, string>>();



                                  KeyValuePair< string, string> keyValue= new KeyValuePair< string, string>("KEY1", "VALUE1");



                                  listKeyValPair.Add(keyValue);





                                  share








                                  New contributor




                                  Nagesh Hugar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                  Check out our Code of Conduct.






                                  $endgroup$


















                                    0












                                    $begingroup$

                                    You can List of KeyValuePair to store duplicates



                                    Example :



                                    List< KeyValuePair < string, string>> listKeyValPair= new List< KeyValuePair< string, string>>();



                                    KeyValuePair< string, string> keyValue= new KeyValuePair< string, string>("KEY1", "VALUE1");



                                    listKeyValPair.Add(keyValue);





                                    share








                                    New contributor




                                    Nagesh Hugar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                    Check out our Code of Conduct.






                                    $endgroup$
















                                      0












                                      0








                                      0





                                      $begingroup$

                                      You can List of KeyValuePair to store duplicates



                                      Example :



                                      List< KeyValuePair < string, string>> listKeyValPair= new List< KeyValuePair< string, string>>();



                                      KeyValuePair< string, string> keyValue= new KeyValuePair< string, string>("KEY1", "VALUE1");



                                      listKeyValPair.Add(keyValue);





                                      share








                                      New contributor




                                      Nagesh Hugar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                      Check out our Code of Conduct.






                                      $endgroup$



                                      You can List of KeyValuePair to store duplicates



                                      Example :



                                      List< KeyValuePair < string, string>> listKeyValPair= new List< KeyValuePair< string, string>>();



                                      KeyValuePair< string, string> keyValue= new KeyValuePair< string, string>("KEY1", "VALUE1");



                                      listKeyValPair.Add(keyValue);






                                      share








                                      New contributor




                                      Nagesh Hugar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                      Check out our Code of Conduct.








                                      share


                                      share






                                      New contributor




                                      Nagesh Hugar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                      Check out our Code of Conduct.









                                      answered 5 mins ago









                                      Nagesh HugarNagesh Hugar

                                      1




                                      1




                                      New contributor




                                      Nagesh Hugar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                      Check out our Code of Conduct.





                                      New contributor





                                      Nagesh Hugar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                      Check out our Code of Conduct.






                                      Nagesh Hugar is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
                                      Check out our Code of Conduct.






























                                          draft saved

                                          draft discarded




















































                                          Thanks for contributing an answer to Code Review Stack Exchange!


                                          • Please be sure to answer the question. Provide details and share your research!

                                          But avoid



                                          • Asking for help, clarification, or responding to other answers.

                                          • Making statements based on opinion; back them up with references or personal experience.


                                          Use MathJax to format equations. MathJax reference.


                                          To learn more, see our tips on writing great answers.




                                          draft saved


                                          draft discarded














                                          StackExchange.ready(
                                          function () {
                                          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f102026%2fduplicatedictionary-a-dictionary-like-class-which-allows-duplicates%23new-answer', 'question_page');
                                          }
                                          );

                                          Post as a guest















                                          Required, but never shown





















































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown

































                                          Required, but never shown














                                          Required, but never shown












                                          Required, but never shown







                                          Required, but never shown







                                          Popular posts from this blog

                                          Costa Masnaga

                                          Fotorealismo

                                          Sidney Franklin