[SalesForce] How is it possible to cast Set to (Iterable)

I am pretty sure that I am missing something obvious here, but I still cannot grasp the casting operation in the following piece of code:

Set<String> mySet = new Set<String>();
mySet.add('One');
mySet.add('Two');
String mySet_Joined = String.join((Iterable<String>) mySet, ', ');

I read this post Do Apex collections implement iterable?, where we saw that Set does not implement either Iterable, nor Iterator interface.

System.debug((new set<String>()) instanceOf Iterable<Object>);
DEBUG|false

System.debug((new set<String>()) instanceOf Iterator<Object>);
DEBUG|false

Then I looked at this documentation article Classes and Casting and realized that in order to be cast to Iterable<String> mySet must implement Iterable. So I would expect exception to be thrown when this line gets executed (Iterable<String>) mySet, but it is not.

Can someone please explain how that is possible?

Best Answer

This is one of those cases where the Type system just falls flat. Set does actually implement the methods for being an Iterable, as mentioned by the methods in the documentation, but does not officially "implement" it (System.assert(stringSet instanceOf Iterable<String>) fails).

The net result is that we have a hybrid object that fails to compile when you try to use it in a context that expects an Iterable, but does work in other cases where you'd expect it to work (and some places you wouldn't, based on other behavior). Salesforce.com has been made aware that types are inherently broken, but there's no idea when or if it'll be fixed.

For now, I'd say that you should not use that method. The reason why is because the cast will ultimately cause Apex Hammer Tests to fail when/if they try to fix this bug, which will mean they'll have to either version it into the compiler, or not be able to fix it at all.

How I would address this for now is to use the slightly more obtuse List constructor:

String mySet_Joined = String.join(new List<String>(mySet), ', ');

This won't fail in future versions but will allow salesforce.com to fix the Iterable/Iterator problem on the Set class. In the meantime, I'll try and get a hold of some people over at salesforce.com to see if I can get more insight on the matter.

When/if I get an answer about this, I'll revise this answer with a recommendation on if you should be casting to Iterable or not.

Related Topic