Grouping records is a pretty common pattern, enough so to write a simple library for it. Something like:
public class GroupBy
{
public Map<Id, List<SObject>> ids(SObjectField field, List<SObject> records)
{
Map<Id, List<SObject>> grouped = new Map<Id, List<SObject>>();
for (SObject record : records)
{
Id parentId = (Id)record.get(field);
if (!grouped.containsKey(parentId))
grouped.put(parentId, new List<SObject>());
grouped.get(parentId).add(record);
}
return grouped;
}
}
That's all well and good, but I recently found someone who had abused this code (likely accidentally) to produce a statement I was sure should produce a runtime exception:
List<ThatObject__c> those; // = ...;
Map<Id, List<ThisObject__c>> byParent = GroupBy.ids(ThatObject__c.Parent__c, those);
So now we have a series of List<ThisObject__c>
whose contents are all ThatObject__c
records!
You can even simplify the behavior and run the following in Execute Anonymous
without issue:
static List<SObject> genericize(List<SObject> input)
{
List<SObject> output = new List<SObject>();
for (SObject record : input) output.add(record);
return output;
}
List<ThisObject__c> these = genericize([SELECT Id FROM ThatObject__c]);
This sure seems like it should generate a runtime exception. Again, this boils down to the platform allowing a List<SomeType>
where none of the elements are actually an instance of SomeType
. I imagine you could extend the finding to interfaces and abstract classes. Is this behavior a bug?