1

It seems like no. I have a utility method

   public static Map<String, SObject> getMapOfStringToSObject(List<SObject> lstSObjs, String strKeyFieldName)
   {
       Map<String, SObject> mapStringToSObject = new Map<String, SObject>();
       for (SObject so : lstSObjs)
           mapStringToSObject.put((String)so.get(strKeyFieldName), so);
   return mapStringToSObject;

}

But when I try to use it (with casting) I get System.TypeException: Invalid conversion from runtime type Map<String, SObject> to Map<String, MyObject> ()

Client code is

Map<String, MyObject> res = (Map<String, MyObject>)UtilsClass.getMapOfStringToSObject(someList, 'someStringField');

Sure I could not cast and loop over the results. But the whole point of this is to abstract away the looping and not have to write it over and over. I have similar methods (where I can cast successfully) that return a variety of types including among others

Map<String, List<SObject>>
Map<Id, List<SObject>>
Todd
  • 193
  • 7
  • Don't think you can do this. MyObject is not an sObject – alesremta Jun 22 '20 at 19:56
  • 1
    is MyObject in your example code an apex class type? – Mark Pond Jun 22 '20 at 19:56
  • This is a topic that has been touched on before I explain at a high level how up-casting and down-casting work https://salesforce.stackexchange.com/a/297775/54609. Furthermore I suggest you look at this post as well that goes into finer detail about problems with type casting in apex https://salesforce.stackexchange.com/a/125891/54609 – Zach Hutchins Jun 23 '20 at 14:16

2 Answers2

0

Provided that MyObject is an SObject (which it should be, given your code so far), the best I've been able to come up with is something like

Map<String, MyObject> res = new Map<String, MyObject>(UtilsClass.getMapOfStringToSObject(someList, 'someStringField').values());

Which makes use of the map constructor which takes a list.

Unfortunately, that forces you to use the record Id as the map key. In limited situations, you could use the field aliasing trick (in a query that uses GROUP BY) to make some other field be the "Id", but I have a feeling that's not going to work for your utility class.

I don't think it's practical to avoid a loop here.

Derek F
  • 61,401
  • 15
  • 50
  • 97
0

I found a way to do this that's only slightly clunky. If I tell my method the return type I want, I can instantiated it with newInstance()

public static Map<String, SObject> getMapOfStringToSObject(List<SObject> lstSObjs, String strKeyFieldName, Type mapType)
{
    Map<String, SObject> mapStringToSObject = (Map<String, SObject>) mapType.newInstance();
    for (SObject so : lstSObjs)
        mapStringToSObject.put((String)so.get(strKeyFieldName), so);
return mapStringToSObject;

}

And client code:

Map<String, Account> res = (Map<String, Account>)UtilsCollection.getMapOfStringToSObject(accounts, 'Name', Map<String, Account>.class);
Todd
  • 193
  • 7