Contains returning False despite same hashcode and Equals returning true
In my log output:
Existing hashcode 170042874 New hashcode 170042874, True
My classes: (Have removed irellevant fields)
21 Replies
I would expect Contains to return True if the hashcodes match and equals returns true
consider implementing
IEquatable<QcPhotoSet>
then it should work
and why are your equals methods protected?
that could also be it tbhthe public one is calling the protected one if it's the right type
that's just how rider generates them
I tried this and it didn't work
just so I can try and reproduce this, what type is
product.QcPhotoSets
?[Required] public ISet<QcPhotoSet> QcPhotoSets { get; set; } = new HashSet<QcPhotoSet>();
Although give me a second to check that
cause Product is coming from EF
so maybe it changes the type of that when it returns it from DB
Just checked the type at runtime and it's still a hashet
My theory was that EF was doing some weird shit and using it's own ISet implementation where Contains doesn't work properly but I guess not
I have lazy loading and shit disabled
this unit test also passes fine so I genuinely have no idea what is going on here
interesting
oooh
I know why
your hashcode depends on non-readonly values
thats a nogo
but the hashcodes are the same
when I log it
I chagned your hashcode method
and it works
assuming source is a string
it wasnt specified, so I guessed
:p
this works with and without equatable
my current code works fine in my unit test
Source is an enum
it's cached for classes, no?
actually it can't be if it's called directly
logger.LogInformation("Existing hashcode {ExistingHashCode} New hashcode {NewHashCode}, {Equal}", existingQcPhotoSet.GetHashCode(), qcPhotoSet.GetHashCode(), existingQcPhotoSet.Equals(qcPhotoSet));
This log only fires if contains returned False
Existing hashcode 1581568506 New hashcode 1581568506, True
hashcodes are the same and equals returned true
inside the "not contains block"
and no data changed
so the hashcode should be the same when I call the if statement as well 🤷
I don't think non readonly is the issue?well, here is my test sample
I have two of these, called a and b
both set up "from scratch" so to speak
a set with just a in it did NOT contain b at first
but after I changed QcPhotoSets hashcode, it did
hm
seems to work too
actually now im really confused. its saying yes to the original code now too
but it didnt at first :d
My existing code passes this test
which I believe is the same as what you're doing?
pretty much, yes
I might just give up and use a
.Any(q => q.Equals(qcPhotoSet))
lol
I genuinely have no idea what is causing thishm
well
are you mutating your QcPhotoSets at all after inserting them into any
Set
?
because that would be a problem
but it wouldnt be the cause of this problem, I thinkSo wait when I call Contains does it compute the hashcode then and there
or is it cached?
I woudln't be suprised if that cuased issues when using EF
Id assume it calculates for b, but compares it to all known a
which ARE cached
since the internals for a HashSet uses the hashcode to index an array
its a bit tricky using equals on collections, which is why
SetEqual
etc exists
sanity check time
lets see if it works if it's just basing on equals
@Pobiega omg that worked :notecrine:
Alright lesson learned
you were right
Now to figure out what I should base my hashcodes of off since evverything is properties lol
ty for the help guys
Ah I understand the issue now
EF Gets a product
EF then gets the Qc Photo Sets (but not the Qc Photos within them) and adds them to the products set based off the computed hash currently
Then EF adds the Qc Photos within the Qc Photo sets and the hashcode is changed but their slot in hashset is based off old hashcode
Just gonna change my implementation to use a List and remember to always check Contains because there isn't really anything meaningful I can generate the hashcode from that won't cause this issue