-1

I have class:

public class Item
{
    public List<int> val { get; set; }
    public string info { get; set; }
}
public class IndexedDictionary : KeyedCollection<List<int>, Item>
{
    protected override List<int> GetKeyForItem(Item item)
    {
        return item.val;
    }
}

In 'main()' method:

    IndexedDictionary dic = new IndexedDictionary();
    dic.Add(new Item() { val = new List<int>() { 1, 2, 3 }, info = "Hello" });
    dic.Add(new Item() { val = new List<int>() { 1 }, info = "Bla.." });
    Console.WriteLine(dic[0].info);
    Console.WriteLine(dic[new List<int>() { 1 }].info);
    Console.ReadLine();

I get error in line:

        Console.WriteLine(dic[new List<int>() { 1 }].info);

Can you correct my code? Tks all

3 Answers3

2

The mistake you are making here is assuming that two instances of a List<int> are the same because they contain the same int. They are not, they are two completely different instances.

So what you would need to do is assign the new List<int>() { 1 } to a local variable, and use that variable as your key.

Something like:

var l1 = new List<int>() { 1 };
dic.Add(new Item() { val = l1, info = "Bla.." });
CodingGorilla
  • 19,612
  • 4
  • 45
  • 65
1

When comparing Lists, your dictinary compares the instances(by default) not the sequence. For ex, below code will give false

bool b = new List<int>() { 1 }.Equals(new List<int>() { 1 })

Therefore you should implement IEqualityComparer. Change your IndexedDictionary as below and it will work.

public class IndexedDictionary : KeyedCollection<List<int>, Item>
{
    public IndexedDictionary() : base(new MyEqualityComparer())
    {
    }

    protected override List<int> GetKeyForItem(Item item)
    {
        return item.val;
    }

    public class MyEqualityComparer : IEqualityComparer<List<int>>
    {
        public bool Equals(List<int> x, List<int> y)
        {
            return x.SequenceEqual(y);
        }

        public int GetHashCode(List<int> obj)
        {
            return obj.Aggregate(0, (s, x) => s ^= x.GetHashCode());
        }
    }
}
L.B
  • 114,136
  • 19
  • 178
  • 224
  • 1
    While this hashcode method will work, I would suggest two changes. One, as it is the hash is independent of order, which is undesirable if order matters. I prefer the algorithm of `int temp = someprime; foreach(int other in ...) temp = (temp + other) * someprime;`. Also, hashing *all* items can be a problem if the list gets large. Consider using a `Take(x)` first to only has the first x items. As long as X isn't too too small the slightly higher collision rate may be worth the lower hash code generation cost. – Servy Nov 14 '12 at 15:12
0

It fails because you are comparing two different objects. It does not make much sense to use a List<int> as key as your dictionary will not care about the contents of those lists.

For instance:

 var list1 = new List<int>() { 1, 2, 3 };
 var list2 = new List<int>() { 1, 2, 3 };

 Console.WriteLine("Equals: {0}", list1 == list2);
 Console.WriteLine("SequenceEquals: {0}", list1.SequenceEqual(list2));
 Console.Read();

The first is false and second is true.

See this question for more information: Is there a built-in method to compare collections in C#?

Community
  • 1
  • 1
qstebom
  • 719
  • 4
  • 12