Bug in List.contains for Id data type?
Looks like this bug System.hashCode broken on Id properties of SObjects? remains unfixed.
Diagnosis is made more confusing because of this hashCode() is never called when adding to Maps and Sets where the debug level determines if hashCode
is called or not.
Sounds like it may be an edge case; it returns true in my org:
09:28:48.2 (4756791)|SYSTEM_METHOD_ENTRY|[7]|System.debug(ANY)
09:28:48.2 (4767250)|USER_DEBUG|[7]|DEBUG|true
09:28:48.2 (4775541)|SYSTEM_METHOD_EXIT|[7]|System.debug(ANY)
Please consider submitting a bug if you have a valid reproduction that support can use. In the general case, you should be able to use contains as intended.
I can repo this on na37.
List<Id> myIdList = new List<Id>();
myIdList.add('0060E000008PdMk');
Id oppId ='0060E000008PdMk';
System.assert(oppId == myIdList[0]); // true
System.assert(myIdList.contains(oppId)); // false - assertion failed !!
Changing the types of the List and the variable to String
causes this code to run as expected.
It looks like the HashCodes under the surface don't match up. This example casts our ids to objects, and calls HashCode
on them, then compares them. They fail, despite the values being the same.
You can cause the contains
to find the value by changing the debug level of "Apex Code" to FINEST
. This (According to @KeithC) causes the comparison to not use HashCode
and use equals
instead, and results in a true
value from contains
.
List<Id> myIdList = new List<Id>();
// Added extra characters to ensure it wasnt something with 15/18 char ids
myIdList.add(((Id)'0060E000008PdMkOIP'));
Id oppId = '0060E000008PdMkOIP';
Integer oppHash = ((Object)oppId).hashCode();
Integer listHash = ((Object)myIdList[0]).hashCode();
System.assertEquals(oppHash, listHash); // !! Fails!! - hash values differ
System.assert(oppId.equals(myIdList[0])); // true
// !! Setting debug APEXCODE to FINEST results in true
System.assert(myIdList.contains(oppId)); // false