It looks like duplicate sObjects can coexist in the same set, while duplicate class instances cannot. Is this a bug or the intended behavior?
This post and this post discuss a similar issue, but the accepted answers seem to indicate that this is a result of the field values being different for each "duplicate" set member, having been changed after being retrieved in separate queries or separately instantiated.
This doesn't seem to apply to my case because the duplicates added to the set all reference the same instance, as confirmed by the tests below.
Test with sObject:
Contact original = new Contact();
original.FirstName = 'original';
Set<Contact> someSet = new Set<Contact>();
someSet.add(original);
for(integer i = 0; i < 2; i++){
original.FirstName = 'changed ' + String.valueOf(i);
for(Contact c : someSet){
System.assertEquals(original,c);
}
someSet.add(original);
}
System.debug('set size: ' + someSet.size());
for(Contact c : someSet){
System.debug(c);
}
Integer q = 1;
for(Contact c : someSet){
c.FirstName = 'changed again ' + String.valueOf(q);
q++;
System.debug(original.FirstName);
}
/*
debug:
set size: 3
Contact:{FirstName=changed 1}
Contact:{FirstName=changed 1}
Contact:{FirstName=changed 1}
changed again 1
changed again 2
changed again 3
*/
Test with Apex class:
public class SomeClass {
public String s;
}
SomeClass original = new SomeClass();
original.s = 'original';
Set<SomeClass> someSet = new Set<SomeClass>();
someSet.add(original);
for(integer i = 0; i < 2; i++){
original.s = 'changed ' + String.valueOf(i);
for(SomeClass c : someSet){
System.assertEquals(original,c);
}
someSet.add(original);
}
System.debug('set size: ' + someSet.size());
for(SomeClass c : someSet){
System.debug(c);
}
Integer q = 1;
for(SomeClass c : someSet){
c.s = 'changed again ' + String.valueOf(q);
q++;
System.debug(original.s);
}
/*
debug log:
set size: 1
SomeClass:[s=changed 3]
changed again 1
*/