13

This situation came up in code review and I was sure the old version should have caused a compile fail:

List<Child__c> children = new List<Child__c>();
for (Parent__c parent : parents)
{
    children.add(parent.Children__r);    // old version
    children.addAll(parent.Children__r); // new version
}

Obviously, this code blew up as soon as it was run against a parent having multiple children (or none). Now, I understand why it is allowed, since you can assign a query result to a single record or to a collection. It just seems like this behavior should not be allowed for a related list. My question is, should this code have failed to compile? Is it a compiler bug, odd quirk of the language, or something else entirely?

1
  • 1
    I don't think it would have failed to compile. It's definitely more of a runtime exception E.g., Account a = [select Name from Account] will compile but will throw a runtime exception if there are more than 1 or no record. So something similar to this construct, adding it to the list would still compile but fail only in the scenario you have mentioned.
    – Jayant Das
    Aug 22, 2018 at 15:35

1 Answer 1

12

Yes, it's always legal to assign a List<SObject> that came from a query into a SObject variable, and it will succeed during runtime only if there's exactly one element. Note that child objects are always considered to have come from a query, so the following code compiles (but obviously crashes):

Account a = new Account();
Contact c = a.Contacts;

However, this is not true for native lists:

// Does not compile //
Account a = new Account[1];

Any time the compiler thinks that a particular list may have come from a query, it will allow this automatic assignment.

Obviously, since the risk for runtime errors exists, you should only use this code syntax if you are absolutely certain only one row will be returned.

This is a convenience syntax that has been around since the beginning of Apex. I'm not even sure if it's in the documentation, and honestly, it's more trouble than its worth most of the time; if it had been up to me, I would not allowed this syntax to exist, since it is so easy to create code that looks fine but crashes "randomly."

You must log in to answer this question.

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