9

I was trying to use set.addAll method with a list of SObject, but I was not able to make it work. Is there any restriction with this data type?

Documentation doesn't mention any: Salesforce Set methods doc

List<String> myList = new List<String>{'Test1','Test2','Test3'};
System.debug(myList);
Set<String> mySet = new Set<String>();
Boolean areInserted = mySet.addAll(myList);
System.debug(areInserted);
System.debug(mySet);
System.debug('Check with SObjectType');
Schema.DescribeFieldResult productFieldResult = Schema.sObjectType.MyObject__c.fields.Product__c;
List<SObjectType> fieldResults = productFieldResult.getReferenceTo();
System.debug(fieldResults);
Set<SObjectType> fieldResultsSet = new Set<SObjectType>();
Boolean areInserted2 = fieldResultsSet.addAll(fieldResults);
System.debug(areInserted2);
System.debug(fieldResultsSet);
System.debug('Try with loop');
List<SObjectType> mySet2 = new List<SObjectType>();
for(SObjectType objType : fieldResults)
{
    mySet2.add(objType);
}
System.debug(mySet2);

Finds here the debug result.

enter image description here

Thanks, Agustina

2 Answers 2

2

On the subject of whether contains works or not, I couldn't find a failing case with these simple tests (whether using standard or custom objects):

@isTest
private class SetTest {

    @isTest
    static void containsAndAddAll() {

        Set<SObjectType> s = new Set<SObjectType>{
                Contact.SObjectType,
                Account.SObjectType
                };
        assertContactAndAccountOnly(s);

        Set<SObjectType> ss = new Set<SObjectType>();
        ss.addAll(s);
        assertContactAndAccountOnly(ss);
    }

    private static void assertContactAndAccountOnly(Set<SObjectType> s) {

        System.assertEquals(false, s.contains(Task.SObjectType));
        System.assertEquals(true, s.contains(Contact.SObjectType));
        System.assertEquals(true, s.contains(Account.SObjectType));
        System.assertEquals(false, s.contains(Note.SObjectType));
        System.assertEquals(2, s.size());
    }

    @isTest
    static void addAndRemove() {

        Set<SObjectType> s = new Set<SObjectType>();

        // Add
        System.assertEquals(0, s.size());
        s.add(Note.SObjectType);
        System.assertEquals(1, s.size());
        s.add(Task.SObjectType);
        System.assertEquals(2, s.size());
        System.assertEquals(true, s.contains(Task.SObjectType));
        System.assertEquals(true, s.contains(Note.SObjectType));

        // Remove
        s.remove(Note.SObjectType);
        System.assertEquals(1, s.size());
        System.assertEquals(true, s.contains(Task.SObjectType));
        System.assertEquals(false, s.contains(Note.SObjectType));
        s.remove(Task.SObjectType);
        System.assertEquals(0, s.size());
        System.assertEquals(false, s.contains(Task.SObjectType));
        System.assertEquals(false, s.contains(Note.SObjectType));
    }
}
1
  • You are adding set.addAll(Set<SObjectType>) and my issue was with set.addAll(List<SObjectType>). However y tried again and works now. Apologize. Commented Mar 31, 2014 at 10:37
9

The problem you are seeing is that for some reason the string representation of Set and List when they contain SObjectType is wrong making it appear that they are empty. If you invoke other methods such as size or contains you will see the behaviour you expect. Your test hints at that by addAll returning true.

I'd call this behaviour a bug, but I don't think the string representation is documented anywhere...

A work around (to help with debugging) would be to write a utility method that builds the string representation by iterating over the content and appending to a string e.g.:

public class Util {
    public static String toString(Set<SObjectType> sobTypes) {
        return toString(new List<SObjectType>(sobTypes));
    }
    public static String toString(List<SObjectType> sobTypes) {
        // Note that String.join doesn't work here at present
        String s = '';
        for (SObjectType sobType : sobTypes) {
            if (s != '') {
                s += ', ';
            }
            s += sobType;
        }
        return '{' + s + '}';
    }
}
9
  • 1
    Ah beat me to it Keith! Nice one! Commented Mar 28, 2014 at 12:41
  • 1
    @AndrewFawcett Think I'd seen this problem in my own debugging before - a real time waster.
    – Keith C
    Commented Mar 28, 2014 at 12:47
  • 1
    Yeah I can imagine, btw, rollout the new String.join function in your above example to make a little leaner... ;-) Commented Mar 28, 2014 at 12:50
  • 1
    @AndrewFawcett Aaargh keep doing this. I'll change it thanks.
    – Keith C
    Commented Mar 28, 2014 at 12:51
  • 1
    @AndrewFawcett Tried String.join for a couple of SObjectTypes and it output "{common.apex.runtime.impl.ApexSObjectTypeToken@6d95f8ef, common.apex.runtime.impl.ApexSObjectTypeToken@110a4b1e}"; looks like the handling of these tokens is broken in more than one place...
    – Keith C
    Commented Mar 28, 2014 at 13:02

You must log in to answer this question.

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