6

Im not sure what the problem here is,

i got a HashSet<object> called _itemsToProcess.

Eventually in my code (no multitrheading) i want to remove items from the hashset

_itemsToProcess.Remove(item);

This doesnt work. I also tried

_itemsToProcess.RemoveWhere(i=>i.Equals(item));

Well it looks trivial, but i can guarantee, item is inside _itemsToProcess. I checked in debugging via

_itemsToProcess.Any(item.Equals) // Returns true
_itemsToProcess.Contains(item)   // Returns false

item.GetHashcode() == _itemsToProcess.First().GetHashcode()  // returns true aswell.

The item doesnt implement ICompareable nor IEquatable so im out of ideas here.

Example (Simplified alot, since this is kind of a big thing)

readonly _itemsToProcess = new HashSet<object>();

void getItems()
{
    foreach(object o in getObjects())
         if(meetsCriteria(o)) _itemsToProcess.Add(o);

}



void processItems()
{
   if(_itemsToProcess.Count> 0)
   { 
      foreach(object item in _itemsToProcess.Where(criteria).ToArray())
          processItem(item);
   }
}

// This gets called in different ways
void processItem(object item)
{ 
     ... do stuff
     if(succes)
         _itemsToProcess.Remove(item);
}

So Rephrasing the problem

var compare = _itemsToProcess.First();
compare.GetHashcode() == item.GerHashcode() // true
compare.Equals(item) // true

_itemsToProcess.Contains(item)  // false, why?
CSharpie
  • 9,195
  • 4
  • 44
  • 71
  • 9
    This would happen if your `GetHashCode()` or `Equals()` methods are broken – SLaks Feb 21 '14 at 16:25
  • 2
    Does it implement `IEquatable`? – Douglas Feb 21 '14 at 16:25
  • Please, do not include a languge tag in a title unless it wouldn't made sense without it. Tags serve this purpose. – Ondrej Janacek Feb 21 '14 at 16:26
  • Make sure you find the item by some unique property – AD.Net Feb 21 '14 at 16:26
  • 1
    At this point a minimal example reproducing the bug would help :). – dureuill Feb 21 '14 at 16:29
  • 1
    Is that code actually what you're writing or are you leaving out your LINQ expressions for brevity? – NWard Feb 21 '14 at 16:29
  • The items in _itemsToProcess are selected by a linq Where and then also with a ToArray() . – CSharpie Feb 21 '14 at 16:34
  • Does your item's class override the `Equals` or `GetHashCode` methods? – Douglas Feb 21 '14 at 16:35
  • Please show the code for Equals and GetHashCode for the class of `item` – Georg Feb 21 '14 at 16:35
  • I cant, this is way too companyspecific to simplyfy here in any means. I suppose i have to focus on those methods then. Im not sure why Equals returns true then and also why Hashcodes are the same. – CSharpie Feb 21 '14 at 16:39
  • Hashcodes are allowed to be the same - that is called a collision. In fact, it is a good thing that collisions happen, because it is very important to the proper operation of a hash table. – Katie Kilian Feb 21 '14 at 16:45
  • 1
    See here for more information on how this stuff is supposed to work: http://stackoverflow.com/questions/371328/why-is-it-important-to-override-gethashcode-when-equals-method-is-overridden – Katie Kilian Feb 21 '14 at 16:45
  • I guess i figured it out while driving home. When the item is added to the hashset, it has a different hashcode, since there may be some properties changing while processing the item. As this is an implementation way down in a baseclass, this probably will casue some sideeffects when fixig... – CSharpie Feb 21 '14 at 17:04
  • @CSharpie You are right, hash codes need to remain constant through the life of the object (or at least while it's in a `HashSet` or `Dictionary`. – D Stanley Feb 21 '14 at 17:07

1 Answers1

5

So the answer is:

when the item was added to the Hashset, the GetHashcode returned a different value. Since the processing seemed to change a propertie that was taken into account in that method, the gethashcode returned a different value at the end.

So this explains why even contains didnt work.

Thank you for your help.

CSharpie
  • 9,195
  • 4
  • 44
  • 71