1
Map<Id, SObject> sObjectMap = new Map<Id, SObject> ();
System.debug(sObjectMap instanceof Map<Id, Account>); // false
System.debug(sObjectMap.values() instanceof List<Account>); // true

Map<Id, Account> accountMap = (Map<Id,Account>) sObjectMap; // error
List<Account> accountList = (List<Account>) sObjectMap.values(); //success

Why can't I treat maps in the same way I do lists?
Why can I cast newMap.values() to List<Account> but I can't cast newMap to a Map<Id,Account>?
And how is the List<SObject> an instance of subtypes but the same does not apply for Map<Id, SObject>?

3
  • 1
    It is as it is. The "Why" is only known to the Salesforce Apex language designers. You simply have to live with it.
    – Phil W
    Commented Jun 28, 2019 at 10:59
  • I'm sorry but I cant accept this as an answer...
    – AshK
    Commented Jun 28, 2019 at 13:23
  • That's your prerogative, but I don't think you'll get a better one. (Note this was actually just a comment, not an answer.)
    – Phil W
    Commented Jun 28, 2019 at 13:33

1 Answer 1

1

Casting collections is a bit different than casting objects of non-collection types.

Based on the Collection Casting documentation, what you're trying to do with your map should likely work. However, most examples of casting that you'll find are examples of up-casting.

The following works just fine

Map<Id, Account> acctMap = new Map<Id, Account>();
Map<Id, SObject> sobjMap = (Map<Id, SObject>)acctMap;

What you're trying to do here, however, is down-casting. Down-casting is a bit of an oddity. It can work, but the requirements are more strict than with up-casting.

The following example will work

Map<Id, Account> acctMap1 = new Map<Id, Account>();
acctMap1.put('001000000000000AAA', new Account(Id = '001000000000000AAA'));
Map<Id, SObject> sobjMap = (Map<Id, Account>)acctMap1;
Map<Id, Account> acctMap2 = (Map<Id, Account>)sobjMap;

If you start with a map of the correct type, you can up-cast it, and then later down-cast it. Why this works and your example doesn't is something I'm not well-equipped to answer. Like Phil W mentioned, that's something that you'd need to ask the people at Salesforce that maintain the Apex language about.

I did some investigation on why we can't up-cast Sets, and managed to come up with a plausible explanation with type-erasure in Java, but I'm not sure if that applies to this situation as well.

Bonus information

instanceOf isn't really reliable when working with collections, see sfdcfox's answer on this question for more details.

Keeping track of collection types in your head is one option. Another option is to use the getSObjectType() method of the List and Map collection types. It doesn't seem to work with Map<Id, SObject> though...

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .