function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
loneboatloneboat 

Did Salesforce.com's Winter '12 version change/break Set.contains() method?

We have our sandbox upgraded to Winter '12, but our production environment is still on the old version. The following code prints "false" on our sandbox, but "true" on production. I can't seem to find mention of this on line, but it looks like they work differently!

 

Set<Id> x = new Set<Id>{
     '012A0000000qv2wIAA'
    ,'012A0000000qv2xIAA'
    ,'012A0000000qv2yIAA'
    ,'012A0000000qv2zIAA'
};

System.debug(x.contains('012A0000000qv2z'));

Note that the Set contains 18-character IDs, and we're asking if it .contains() a 15-character ID.  I don't mind it working one way or the other;  just weird that it's behaving differently.

Best Answer chosen by Admin (Salesforce Developers) 
Jia HuJia Hu

As doc said,

http://www.salesforce.com/us/developer/docs/apexcode/Content/langCon_apex_primitives.htm

if you set ID to a 15-character value, Apex automatically converts the value to its 18-character representation.

 

Therefore, if you use

ID aid = '012A0000000qv2z';  It is the same with a 18-digits ID in the Apex.

 

In the old version, Apex will take x.contains('012A0000000qv2z') as a 18 digit ID, it is strange.

In the new version, it is revised. You have to set the '012A0000000qv2z' as the ID first, and then Apex will turn it to 18 digits ID.

 

test with the code as follows,

 

Set<Id> x = new Set<Id>{
'012A0000000qv2wIAA'
,'012A0000000qv2xIAA'
,'012A0000000qv2yIAA'
,'012A0000000qv2zIAA'
};
System.debug(' ------ ' + x.contains('012A0000000qv2z'));
Id aId = '012A0000000qv2z';
System.debug(' ------ ' + x.contains( aId ));

Set<Id> y = new Set<Id>{
'012A0000000qv2w'
,'012A0000000qv2x'
,'012A0000000qv2y'
,'012A0000000qv2z'
};
System.debug(' ----------- ' + y.contains('012A0000000qv2zIAA'));
System.debug(' ----------- ' + y.contains('012A0000000qv2z'));
System.debug(' ----------- ' + y.contains( aId ));

All Answers

loneboatloneboat

Just noticed that if I explicitly cast the String to an ID, the behavior becomes consistent across environments:

 

System.debug(x.contains((Id)('012A0000000qv2z')));

 So maybe Apex has changed the type-promotion rules in the new release?

crop1645crop1645

I presume you mean Winter 13.

 

I'm surprised that your "contains('15 char string')" versus a set of 18 char IDs ever worked. That said, others, including myself are finding anomalies with Winter 13. Check out http://success.salesforce.com/issues_index?tag=Winter%2013.

 

Note that String conversion to IDs is governed by:

 

"Strings can be assigned to IDs. However, at runtime, the value is checked to ensure that it is a legitimate ID. If it is not, a runtime exception is thrown"

 

Using hard coded IDs in code is not good practice as they don't transfer from sandbox to production except for certain circumstances 

Jia HuJia Hu

As doc said,

http://www.salesforce.com/us/developer/docs/apexcode/Content/langCon_apex_primitives.htm

if you set ID to a 15-character value, Apex automatically converts the value to its 18-character representation.

 

Therefore, if you use

ID aid = '012A0000000qv2z';  It is the same with a 18-digits ID in the Apex.

 

In the old version, Apex will take x.contains('012A0000000qv2z') as a 18 digit ID, it is strange.

In the new version, it is revised. You have to set the '012A0000000qv2z' as the ID first, and then Apex will turn it to 18 digits ID.

 

test with the code as follows,

 

Set<Id> x = new Set<Id>{
'012A0000000qv2wIAA'
,'012A0000000qv2xIAA'
,'012A0000000qv2yIAA'
,'012A0000000qv2zIAA'
};
System.debug(' ------ ' + x.contains('012A0000000qv2z'));
Id aId = '012A0000000qv2z';
System.debug(' ------ ' + x.contains( aId ));

Set<Id> y = new Set<Id>{
'012A0000000qv2w'
,'012A0000000qv2x'
,'012A0000000qv2y'
,'012A0000000qv2z'
};
System.debug(' ----------- ' + y.contains('012A0000000qv2zIAA'));
System.debug(' ----------- ' + y.contains('012A0000000qv2z'));
System.debug(' ----------- ' + y.contains( aId ));

This was selected as the best answer
loneboatloneboat

Thanks for the responses guys.  As for the hard-coded IDs, they're not actually hard-coded in my code.  That's just the result of me whittling down my issue to a simplest-case example.

 

Thanks again!