0

I have a list of entities and I want to check how many of them are common to some of the properties. So I used a dictionary

List<Letter> allPsukim = await _context.Letter.Where(a => a.OrderId == Order.Id)
                                              .ToListAsync();
foreach (var item in allPsukim)
{
    Psukim newPasuk = new Psukim()
    {
        Book = item.Book,
        Pasuk = item.Pasuk,
        Perek = item.Perek
    };

    if (showPsukim.ContainsKey(newPasuk))
    {
        List<int> newList = showPsukim[newPasuk];
        newList.Add(item.Position);
        showPsukim[newPasuk] = newList;
    }
    else
    {
        List<int> newList = new List<int>() { item.Position };
        showPsukim.Add(newPasuk, newList);
    }
}

The problem is that the showPsukim.ContainsKey(newPasuk) always shows that no key exists.

Where can I use entity as a key and check if it exists?

Tatranskymedved
  • 4,194
  • 3
  • 21
  • 47
R-S
  • 151
  • 10
  • if you always "new Psukim ()" , it would be a new key – TimChang Sep 30 '21 at 09:28
  • Thinking about it, the actual "custom object as dictionary key" is not duplicate to this Q. This question would appreciate own adequate answer since having "good" key comparer might not be the best solution. – Tatranskymedved Sep 30 '21 at 09:33

2 Answers2

2

Currently you are comparing Object references and not values. One way to compare Values is to use a string as key that combines the serialized properties that you need for comparison of equality. For example you could key on a concatenation of the Book, the Perek and the Passuk Properties:

string key = item.Book + "-" + item.Perek + "-" + item.Passuk;
dic.Add(key,item);

Then query for the key:

if(dic.ContainsKey(key)){...}

Of course, you could add a Serialize() method to the Letter Class that would return a serialized representation of the Object and use that as a key for your dictionary.

Alternatively you could override the GetHashCode() method.

Manu
  • 28,753
  • 28
  • 75
  • 83
0

If it is reference type , it would be a new key when you new one. So try change to a struct, it's key is same when your field is totally same.

public class Psukim 
{
    //...
}

Change to this:

public struct Psukim 
{
    //...
}

or Override GetHashCode() , And you can choose few field to combine a new key.

public class Psukim 
    {
        //...
    
        public override int GetHashCode()
        {
            // set what you want field to combine a key.
            return System.HashCode.Combine(Book, Perek);
        }

        public override bool Equals(object obj)
        {
            Key other = obj as key;
            return other != null && other.Book == this.Book && other.Perek == this.Perek;
        }
    }
TimChang
  • 2,249
  • 13
  • 25
  • and what if OP wanted to compare only a few properties? Changing a class to a struct for the sake of equality is a really bad idea. – MakePeaceGreatAgain Sep 30 '21 at 09:40
  • I guess this class just for compare , a temp class or struct , if want to compare few members , I think override GetHashCode() is better. – TimChang Sep 30 '21 at 09:46