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|improve this answer










        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$













        • $begingroup$
          Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
          $endgroup$
          – Sᴀᴍ Onᴇᴌᴀ
          5 mins ago











        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|improve this answer










                                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$













                                • $begingroup$
                                  Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
                                  $endgroup$
                                  – Sᴀᴍ Onᴇᴌᴀ
                                  5 mins ago
















                                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|improve this answer










                                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$













                                • $begingroup$
                                  Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
                                  $endgroup$
                                  – Sᴀᴍ Onᴇᴌᴀ
                                  5 mins ago














                                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|improve this answer










                                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|improve this answer










                                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|improve this answer



                                share|improve this answer








                                edited 8 mins ago









                                Sᴀᴍ Onᴇᴌᴀ

                                9,58362164




                                9,58362164






                                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 36 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.












                                • $begingroup$
                                  Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
                                  $endgroup$
                                  – Sᴀᴍ Onᴇᴌᴀ
                                  5 mins ago


















                                • $begingroup$
                                  Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
                                  $endgroup$
                                  – Sᴀᴍ Onᴇᴌᴀ
                                  5 mins ago
















                                $begingroup$
                                Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
                                $endgroup$
                                – Sᴀᴍ Onᴇᴌᴀ
                                5 mins ago




                                $begingroup$
                                Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
                                $endgroup$
                                – Sᴀᴍ Onᴇᴌᴀ
                                5 mins ago


















                                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

                                How to reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

                                is 'sed' thread safe

                                How to make a Squid Proxy server?