Can Cast Child Related List to Single SObject Record - Compiler error?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
13
down vote

favorite
2












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?







share|improve this question
















  • 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 at 15:35

















up vote
13
down vote

favorite
2












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?







share|improve this question
















  • 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 at 15:35













up vote
13
down vote

favorite
2









up vote
13
down vote

favorite
2






2





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?







share|improve this question












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?









share|improve this question











share|improve this question




share|improve this question










asked Aug 22 at 15:25









Adrian Larson♦

100k19105223




100k19105223







  • 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 at 15:35













  • 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 at 15:35








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 at 15:35





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 at 15:35











1 Answer
1






active

oldest

votes

















up vote
12
down vote



accepted










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."






share|improve this answer




















    Your Answer







    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "459"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f229763%2fcan-cast-child-related-list-to-single-sobject-record-compiler-error%23new-answer', 'question_page');

    );

    Post as a guest






























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    12
    down vote



    accepted










    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."






    share|improve this answer
























      up vote
      12
      down vote



      accepted










      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."






      share|improve this answer






















        up vote
        12
        down vote



        accepted







        up vote
        12
        down vote



        accepted






        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."






        share|improve this answer












        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."







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Aug 22 at 15:44









        sfdcfox

        225k10171384




        225k10171384



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsalesforce.stackexchange.com%2fquestions%2f229763%2fcan-cast-child-related-list-to-single-sobject-record-compiler-error%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            Long meetings (6-7 hours a day): Being “babysat” by supervisor

            Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

            Confectionery