While working on some code for a utility method to remove values from a List
, I wrote this method signature, which accepts a List<Object>
:
public static List<sObject> Exclude(List<sObject> records, List<Object> excluded, String field)
Later, I added another method signature to call this function using a Set<Object>
:
public static List<sObject> Exclude(List<sObject> records, Set<Object> excluded, String field)
Both of these are functionally identical, except for the List
/Set
difference.
Trying to call the method using a Set<Id>
results in this error:
Line: 4, Column: 26
Method does not exist or incorrect signature:
void Exclude(List<Account>, Set<Id>, String)
from the typeTestUtility
However, when calling the method using a List<Id>
, correctly calls the method using the List<Object>
signature. Creating a new List<Id>
based on the Set
also calls the correct method.
Why does the behavior of apex differ between these two list types?
You can test this from your developer console using the below class, and this snippet:
List<Account> accounts = [SELECT Id, Name FROM Account];
Set<Id> failedIds = new Set<Id>();
System.debug(TestUtility.Exclude(accounts, failedIds, 'Id')); // Fails
System.debug(TestUtility.Exclude(accounts, new List<Id>(failedIds), 'Id')); // Works
TestUtility
Class
public class TestUtility {
public static List<sObject> Exclude(List<sObject> records, List<Object> excluded, String field) {
return null;
}
public static List<sObject> Exclude(List<sObject> records, Set<Object> excluded, String field) {
return Exclude(records, new List<Object>(excluded), field);
}
}
Looks like this really isn't possible without some clever type avoidance:
System.debug(someId instanceof Object); // always true
System.debug(new List<Id>() instanceof Object); // always true
System.debug(new List<Id>() instanceof List<Object>); // always true
System.debug(new Set<Id>() instanceof Object); // always true
System.debug(new Set<Id>() instanceof Set<Object>); // Always false
Operation
instanceof
is alwaysfalse
since an instance ofSet<Id>
is never an instance ofSet<Object>
Object
instead ofsObject
for your second param type?System.debug(TestUtility.Exclude(accounts, new List<Id>(failedIds), 'Id'));
fails for me from DEV consoleTestUtility.Exclude(accounts, new List<String>{ 'Seattle', 'Washington, 'Austin' }, 'BillingCity');