2

I am writing a function that receives parameters that implement the interable interface.

Not specific to List or Set (without overloading)

In situations where we don't know what parameters will come in, can we cast them as List or Set?

public void someMethod( Iterable<String> listOrSet ){
   
    // EXCEPTION :: " IN operator must be used with an iterable expression " ...???
    List<Account> accounts = [SELECT Name FROM Account WHERE ID IN: listOrSet ];

    // some more iterable use case
}

1 Answer 1

2

Iterable isn't supported as a bind parameter, either because Database.QueryLocator might break things if used in a bind parameter, or because custom Iterable objects might do something unexpected. I'm not really sure why, but the net result is, we can't use Iterable as a bind parameter.

The closest thing you can do is to manually iterate the object:

public void someMethod(Iterable<String> values) {
    Iterator<String> it = values.iterator();
    Set<String> iteratedValues = new Set<String>();
    while(it.hasNext()) {
        iteratedValues.add(it.next());
    }
    Account[] accounts = [select Name from account where Id = :iteratedvalues];
}

In addition, because of this bug, you can't even make a generic algorithm by using Set<Object> as a collector for the values. Any attempt you make to do so results in either a compiler exception or a runtime exception.

Ultimately, it's easier to to require users to just use one or the other, as you can generally construct a List from a Set, and a Set from a List, using the one-parameter constructor that accepts a List or Set (e.g. Set<String> stringSet = new Set<String>(stringList)).

If the bugs were ever fixed, we could do away with code like this, but there's no telling when, or if, such an incredibly widespread bug might ever be fixed.

You must log in to answer this question.

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