Why is LINQ non-deterministic?











up vote
1
down vote

favorite












I randomly sorted an IEnumerable. I keep printing out the same element, and getting a different result.



string collection = {"Zero", "One", "Two", "Three", "Four"};
var random = new Random();
var enumerableCollection = collection.OrderBy(e => random.NextDouble());

Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));


Every write gives a different random element. Why is the order not preserved?



See it on .NET Fiddle










share|improve this question




















  • 2




    Why would you expect it to return the same value every time?
    – mjwills
    1 hour ago






  • 2




    Possible duplicate of Is there a way to Memorize or Materialize an IEnumerable?
    – mjwills
    1 hour ago






  • 6




    The key thing to understand is that LINQ queries do nothing until they are materialised (e.g. ToList, ToArray, foreach, ElementAt). You aren't executing the query once and then getting the first element. You are materialising it five separate times. So each time, it orders it differently - like you told it to.
    – mjwills
    1 hour ago








  • 4




    @Evorlor Read the remarks section: "This method is implemented by using deferred execution. The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach". Reusing that IEnumerable (e.g. by materialising it using .ElementAt(0)) will re-execute it.
    – John
    1 hour ago








  • 4




    As a learning exercise, change random.NextDouble() to { return random.NextDouble(); } and put it on its own line of code. Put a breakpoint on it. Run the code. Watch how many times it gets hit.
    – mjwills
    1 hour ago















up vote
1
down vote

favorite












I randomly sorted an IEnumerable. I keep printing out the same element, and getting a different result.



string collection = {"Zero", "One", "Two", "Three", "Four"};
var random = new Random();
var enumerableCollection = collection.OrderBy(e => random.NextDouble());

Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));


Every write gives a different random element. Why is the order not preserved?



See it on .NET Fiddle










share|improve this question




















  • 2




    Why would you expect it to return the same value every time?
    – mjwills
    1 hour ago






  • 2




    Possible duplicate of Is there a way to Memorize or Materialize an IEnumerable?
    – mjwills
    1 hour ago






  • 6




    The key thing to understand is that LINQ queries do nothing until they are materialised (e.g. ToList, ToArray, foreach, ElementAt). You aren't executing the query once and then getting the first element. You are materialising it five separate times. So each time, it orders it differently - like you told it to.
    – mjwills
    1 hour ago








  • 4




    @Evorlor Read the remarks section: "This method is implemented by using deferred execution. The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach". Reusing that IEnumerable (e.g. by materialising it using .ElementAt(0)) will re-execute it.
    – John
    1 hour ago








  • 4




    As a learning exercise, change random.NextDouble() to { return random.NextDouble(); } and put it on its own line of code. Put a breakpoint on it. Run the code. Watch how many times it gets hit.
    – mjwills
    1 hour ago













up vote
1
down vote

favorite









up vote
1
down vote

favorite











I randomly sorted an IEnumerable. I keep printing out the same element, and getting a different result.



string collection = {"Zero", "One", "Two", "Three", "Four"};
var random = new Random();
var enumerableCollection = collection.OrderBy(e => random.NextDouble());

Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));


Every write gives a different random element. Why is the order not preserved?



See it on .NET Fiddle










share|improve this question















I randomly sorted an IEnumerable. I keep printing out the same element, and getting a different result.



string collection = {"Zero", "One", "Two", "Three", "Four"};
var random = new Random();
var enumerableCollection = collection.OrderBy(e => random.NextDouble());

Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));
Console.WriteLine(enumerableCollection.ElementAt(0));


Every write gives a different random element. Why is the order not preserved?



See it on .NET Fiddle







c# linq ienumerable deferred-execution non-deterministic






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 1 hour ago









mjwills

14.1k42439




14.1k42439










asked 1 hour ago









Evorlor

2,658114491




2,658114491








  • 2




    Why would you expect it to return the same value every time?
    – mjwills
    1 hour ago






  • 2




    Possible duplicate of Is there a way to Memorize or Materialize an IEnumerable?
    – mjwills
    1 hour ago






  • 6




    The key thing to understand is that LINQ queries do nothing until they are materialised (e.g. ToList, ToArray, foreach, ElementAt). You aren't executing the query once and then getting the first element. You are materialising it five separate times. So each time, it orders it differently - like you told it to.
    – mjwills
    1 hour ago








  • 4




    @Evorlor Read the remarks section: "This method is implemented by using deferred execution. The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach". Reusing that IEnumerable (e.g. by materialising it using .ElementAt(0)) will re-execute it.
    – John
    1 hour ago








  • 4




    As a learning exercise, change random.NextDouble() to { return random.NextDouble(); } and put it on its own line of code. Put a breakpoint on it. Run the code. Watch how many times it gets hit.
    – mjwills
    1 hour ago














  • 2




    Why would you expect it to return the same value every time?
    – mjwills
    1 hour ago






  • 2




    Possible duplicate of Is there a way to Memorize or Materialize an IEnumerable?
    – mjwills
    1 hour ago






  • 6




    The key thing to understand is that LINQ queries do nothing until they are materialised (e.g. ToList, ToArray, foreach, ElementAt). You aren't executing the query once and then getting the first element. You are materialising it five separate times. So each time, it orders it differently - like you told it to.
    – mjwills
    1 hour ago








  • 4




    @Evorlor Read the remarks section: "This method is implemented by using deferred execution. The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach". Reusing that IEnumerable (e.g. by materialising it using .ElementAt(0)) will re-execute it.
    – John
    1 hour ago








  • 4




    As a learning exercise, change random.NextDouble() to { return random.NextDouble(); } and put it on its own line of code. Put a breakpoint on it. Run the code. Watch how many times it gets hit.
    – mjwills
    1 hour ago








2




2




Why would you expect it to return the same value every time?
– mjwills
1 hour ago




Why would you expect it to return the same value every time?
– mjwills
1 hour ago




2




2




Possible duplicate of Is there a way to Memorize or Materialize an IEnumerable?
– mjwills
1 hour ago




Possible duplicate of Is there a way to Memorize or Materialize an IEnumerable?
– mjwills
1 hour ago




6




6




The key thing to understand is that LINQ queries do nothing until they are materialised (e.g. ToList, ToArray, foreach, ElementAt). You aren't executing the query once and then getting the first element. You are materialising it five separate times. So each time, it orders it differently - like you told it to.
– mjwills
1 hour ago






The key thing to understand is that LINQ queries do nothing until they are materialised (e.g. ToList, ToArray, foreach, ElementAt). You aren't executing the query once and then getting the first element. You are materialising it five separate times. So each time, it orders it differently - like you told it to.
– mjwills
1 hour ago






4




4




@Evorlor Read the remarks section: "This method is implemented by using deferred execution. The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach". Reusing that IEnumerable (e.g. by materialising it using .ElementAt(0)) will re-execute it.
– John
1 hour ago






@Evorlor Read the remarks section: "This method is implemented by using deferred execution. The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach". Reusing that IEnumerable (e.g. by materialising it using .ElementAt(0)) will re-execute it.
– John
1 hour ago






4




4




As a learning exercise, change random.NextDouble() to { return random.NextDouble(); } and put it on its own line of code. Put a breakpoint on it. Run the code. Watch how many times it gets hit.
– mjwills
1 hour ago




As a learning exercise, change random.NextDouble() to { return random.NextDouble(); } and put it on its own line of code. Put a breakpoint on it. Run the code. Watch how many times it gets hit.
– mjwills
1 hour ago












3 Answers
3






active

oldest

votes

















up vote
1
down vote













Many of the previous responses are technically correct, but I think it is useful to look directly at the implementation for Enumerable.



We can see that the the ElementAt calls GetEnumerator, which in turn yields on an iteration of the the current grouping.



If you aren't familiar with yeild see yield.



For the given example, the current grouping is



e => random.NextDouble()


Which means that we are endlessly iteratorating over collection (look at the inifinite loop of the yield) and returning the resolution of the grouping for each element which executes against random.NextDouble().



Therefore, the non-deterministic nature here is due to the non-deterministic nature of the random grouping. This is expected behavior for the LINQ terminal statements (.List(), toArray() ect.) but can be confusing if you attempt to utilize them beforehand.






share|improve this answer








New contributor




Alchemy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

























    up vote
    1
    down vote













    Linq defers execution until it is absolutely necessary. You can think of enumerableCollection as the definition of how you want the enumeration to work, rather than the result of a single enumeration.



    So each time you enumerate it (which you're doing when you call ElementAt) it will re-enumerate your original collection, and since you've chosen to order randomly, the answer is different each time.



    You can make it do what you were expecting by adding .ToList() on the end:



    var enumerableCollection = collection.OrderBy(e => random.NextDouble()).ToList();


    This performs an enumeration, and stores the result in a List. By using this, the original list won't be re-enumerated each time you enumerate the enumerableCollection.






    share|improve this answer




























      up vote
      1
      down vote













      The simple answer is that you are specifically forcing a non-deterministic situation. The why is due to how LINQ functions.



      At its core LINQ is designed around the concept of building objects that represent operations on a set of data - object, records, etc. - and then executing those operations at enumeration time. When you call OrderBy the return is an object that will process the origin to perform the ordering, not a new collection that is ordered. The order is Only when you actually enumerate the data - by calling ElementAt in this case.



      Each time you enumerate the IEnumerable<string> object it runs the sequence of operations you specified, creating a random ordering of the elements. Each ElementAt(0) call will therefore return the first element of a new random sequence.



      Essentially what you appear to be misunderstanding is this: an IEnumerable<T> is not a collection.



      You can however convert the IEnumerable<string> to a collection using ToArray() or ToList(). These will take the output of the operation sequence specified by the IEnumerable<> and create a new collection - string or List<string> respectively.



      For instance:



      string collection = {"Zero", "One", "Two", "Three", "Four"};
      var random = new Random();
      var enumerableCollection = collection.OrderBy(e => random.NextDouble()).ToArray();

      Console.WriteLine(enumerableCollection.ElementAt(0));
      Console.WriteLine(enumerableCollection.ElementAt(0));
      Console.WriteLine(enumerableCollection.ElementAt(0));
      Console.WriteLine(enumerableCollection.ElementAt(0));
      Console.WriteLine(enumerableCollection.ElementAt(0));


      Now you'll get a random item from the original array, but it will be the same item multiple times. Instead of randomizing each time it's just reading the first item in a new collection whose order is randomized.






      share|improve this answer





















        Your Answer






        StackExchange.ifUsing("editor", function () {
        StackExchange.using("externalEditor", function () {
        StackExchange.using("snippets", function () {
        StackExchange.snippets.init();
        });
        });
        }, "code-snippets");

        StackExchange.ready(function() {
        var channelOptions = {
        tags: "".split(" "),
        id: "1"
        };
        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: true,
        noModals: true,
        showLowRepImageUploadWarning: true,
        reputationToPostImages: 10,
        bindNavPrevention: true,
        postfix: "",
        imageUploader: {
        brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
        contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
        allowUrls: true
        },
        onDemand: true,
        discardSelector: ".discard-answer"
        ,immediatelyShowMarkdownHelp:true
        });


        }
        });














         

        draft saved


        draft discarded


















        StackExchange.ready(
        function () {
        StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53348977%2fwhy-is-linq-non-deterministic%23new-answer', 'question_page');
        }
        );

        Post as a guest















        Required, but never shown

























        3 Answers
        3






        active

        oldest

        votes








        3 Answers
        3






        active

        oldest

        votes









        active

        oldest

        votes






        active

        oldest

        votes








        up vote
        1
        down vote













        Many of the previous responses are technically correct, but I think it is useful to look directly at the implementation for Enumerable.



        We can see that the the ElementAt calls GetEnumerator, which in turn yields on an iteration of the the current grouping.



        If you aren't familiar with yeild see yield.



        For the given example, the current grouping is



        e => random.NextDouble()


        Which means that we are endlessly iteratorating over collection (look at the inifinite loop of the yield) and returning the resolution of the grouping for each element which executes against random.NextDouble().



        Therefore, the non-deterministic nature here is due to the non-deterministic nature of the random grouping. This is expected behavior for the LINQ terminal statements (.List(), toArray() ect.) but can be confusing if you attempt to utilize them beforehand.






        share|improve this answer








        New contributor




        Alchemy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
        Check out our Code of Conduct.






















          up vote
          1
          down vote













          Many of the previous responses are technically correct, but I think it is useful to look directly at the implementation for Enumerable.



          We can see that the the ElementAt calls GetEnumerator, which in turn yields on an iteration of the the current grouping.



          If you aren't familiar with yeild see yield.



          For the given example, the current grouping is



          e => random.NextDouble()


          Which means that we are endlessly iteratorating over collection (look at the inifinite loop of the yield) and returning the resolution of the grouping for each element which executes against random.NextDouble().



          Therefore, the non-deterministic nature here is due to the non-deterministic nature of the random grouping. This is expected behavior for the LINQ terminal statements (.List(), toArray() ect.) but can be confusing if you attempt to utilize them beforehand.






          share|improve this answer








          New contributor




          Alchemy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
          Check out our Code of Conduct.




















            up vote
            1
            down vote










            up vote
            1
            down vote









            Many of the previous responses are technically correct, but I think it is useful to look directly at the implementation for Enumerable.



            We can see that the the ElementAt calls GetEnumerator, which in turn yields on an iteration of the the current grouping.



            If you aren't familiar with yeild see yield.



            For the given example, the current grouping is



            e => random.NextDouble()


            Which means that we are endlessly iteratorating over collection (look at the inifinite loop of the yield) and returning the resolution of the grouping for each element which executes against random.NextDouble().



            Therefore, the non-deterministic nature here is due to the non-deterministic nature of the random grouping. This is expected behavior for the LINQ terminal statements (.List(), toArray() ect.) but can be confusing if you attempt to utilize them beforehand.






            share|improve this answer








            New contributor




            Alchemy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.









            Many of the previous responses are technically correct, but I think it is useful to look directly at the implementation for Enumerable.



            We can see that the the ElementAt calls GetEnumerator, which in turn yields on an iteration of the the current grouping.



            If you aren't familiar with yeild see yield.



            For the given example, the current grouping is



            e => random.NextDouble()


            Which means that we are endlessly iteratorating over collection (look at the inifinite loop of the yield) and returning the resolution of the grouping for each element which executes against random.NextDouble().



            Therefore, the non-deterministic nature here is due to the non-deterministic nature of the random grouping. This is expected behavior for the LINQ terminal statements (.List(), toArray() ect.) but can be confusing if you attempt to utilize them beforehand.







            share|improve this answer








            New contributor




            Alchemy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.









            share|improve this answer



            share|improve this answer






            New contributor




            Alchemy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.









            answered 44 mins ago









            Alchemy

            591




            591




            New contributor




            Alchemy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.





            New contributor





            Alchemy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.






            Alchemy is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
            Check out our Code of Conduct.
























                up vote
                1
                down vote













                Linq defers execution until it is absolutely necessary. You can think of enumerableCollection as the definition of how you want the enumeration to work, rather than the result of a single enumeration.



                So each time you enumerate it (which you're doing when you call ElementAt) it will re-enumerate your original collection, and since you've chosen to order randomly, the answer is different each time.



                You can make it do what you were expecting by adding .ToList() on the end:



                var enumerableCollection = collection.OrderBy(e => random.NextDouble()).ToList();


                This performs an enumeration, and stores the result in a List. By using this, the original list won't be re-enumerated each time you enumerate the enumerableCollection.






                share|improve this answer

























                  up vote
                  1
                  down vote













                  Linq defers execution until it is absolutely necessary. You can think of enumerableCollection as the definition of how you want the enumeration to work, rather than the result of a single enumeration.



                  So each time you enumerate it (which you're doing when you call ElementAt) it will re-enumerate your original collection, and since you've chosen to order randomly, the answer is different each time.



                  You can make it do what you were expecting by adding .ToList() on the end:



                  var enumerableCollection = collection.OrderBy(e => random.NextDouble()).ToList();


                  This performs an enumeration, and stores the result in a List. By using this, the original list won't be re-enumerated each time you enumerate the enumerableCollection.






                  share|improve this answer























                    up vote
                    1
                    down vote










                    up vote
                    1
                    down vote









                    Linq defers execution until it is absolutely necessary. You can think of enumerableCollection as the definition of how you want the enumeration to work, rather than the result of a single enumeration.



                    So each time you enumerate it (which you're doing when you call ElementAt) it will re-enumerate your original collection, and since you've chosen to order randomly, the answer is different each time.



                    You can make it do what you were expecting by adding .ToList() on the end:



                    var enumerableCollection = collection.OrderBy(e => random.NextDouble()).ToList();


                    This performs an enumeration, and stores the result in a List. By using this, the original list won't be re-enumerated each time you enumerate the enumerableCollection.






                    share|improve this answer












                    Linq defers execution until it is absolutely necessary. You can think of enumerableCollection as the definition of how you want the enumeration to work, rather than the result of a single enumeration.



                    So each time you enumerate it (which you're doing when you call ElementAt) it will re-enumerate your original collection, and since you've chosen to order randomly, the answer is different each time.



                    You can make it do what you were expecting by adding .ToList() on the end:



                    var enumerableCollection = collection.OrderBy(e => random.NextDouble()).ToList();


                    This performs an enumeration, and stores the result in a List. By using this, the original list won't be re-enumerated each time you enumerate the enumerableCollection.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered 43 mins ago









                    Richardissimo

                    3,9442726




                    3,9442726






















                        up vote
                        1
                        down vote













                        The simple answer is that you are specifically forcing a non-deterministic situation. The why is due to how LINQ functions.



                        At its core LINQ is designed around the concept of building objects that represent operations on a set of data - object, records, etc. - and then executing those operations at enumeration time. When you call OrderBy the return is an object that will process the origin to perform the ordering, not a new collection that is ordered. The order is Only when you actually enumerate the data - by calling ElementAt in this case.



                        Each time you enumerate the IEnumerable<string> object it runs the sequence of operations you specified, creating a random ordering of the elements. Each ElementAt(0) call will therefore return the first element of a new random sequence.



                        Essentially what you appear to be misunderstanding is this: an IEnumerable<T> is not a collection.



                        You can however convert the IEnumerable<string> to a collection using ToArray() or ToList(). These will take the output of the operation sequence specified by the IEnumerable<> and create a new collection - string or List<string> respectively.



                        For instance:



                        string collection = {"Zero", "One", "Two", "Three", "Four"};
                        var random = new Random();
                        var enumerableCollection = collection.OrderBy(e => random.NextDouble()).ToArray();

                        Console.WriteLine(enumerableCollection.ElementAt(0));
                        Console.WriteLine(enumerableCollection.ElementAt(0));
                        Console.WriteLine(enumerableCollection.ElementAt(0));
                        Console.WriteLine(enumerableCollection.ElementAt(0));
                        Console.WriteLine(enumerableCollection.ElementAt(0));


                        Now you'll get a random item from the original array, but it will be the same item multiple times. Instead of randomizing each time it's just reading the first item in a new collection whose order is randomized.






                        share|improve this answer

























                          up vote
                          1
                          down vote













                          The simple answer is that you are specifically forcing a non-deterministic situation. The why is due to how LINQ functions.



                          At its core LINQ is designed around the concept of building objects that represent operations on a set of data - object, records, etc. - and then executing those operations at enumeration time. When you call OrderBy the return is an object that will process the origin to perform the ordering, not a new collection that is ordered. The order is Only when you actually enumerate the data - by calling ElementAt in this case.



                          Each time you enumerate the IEnumerable<string> object it runs the sequence of operations you specified, creating a random ordering of the elements. Each ElementAt(0) call will therefore return the first element of a new random sequence.



                          Essentially what you appear to be misunderstanding is this: an IEnumerable<T> is not a collection.



                          You can however convert the IEnumerable<string> to a collection using ToArray() or ToList(). These will take the output of the operation sequence specified by the IEnumerable<> and create a new collection - string or List<string> respectively.



                          For instance:



                          string collection = {"Zero", "One", "Two", "Three", "Four"};
                          var random = new Random();
                          var enumerableCollection = collection.OrderBy(e => random.NextDouble()).ToArray();

                          Console.WriteLine(enumerableCollection.ElementAt(0));
                          Console.WriteLine(enumerableCollection.ElementAt(0));
                          Console.WriteLine(enumerableCollection.ElementAt(0));
                          Console.WriteLine(enumerableCollection.ElementAt(0));
                          Console.WriteLine(enumerableCollection.ElementAt(0));


                          Now you'll get a random item from the original array, but it will be the same item multiple times. Instead of randomizing each time it's just reading the first item in a new collection whose order is randomized.






                          share|improve this answer























                            up vote
                            1
                            down vote










                            up vote
                            1
                            down vote









                            The simple answer is that you are specifically forcing a non-deterministic situation. The why is due to how LINQ functions.



                            At its core LINQ is designed around the concept of building objects that represent operations on a set of data - object, records, etc. - and then executing those operations at enumeration time. When you call OrderBy the return is an object that will process the origin to perform the ordering, not a new collection that is ordered. The order is Only when you actually enumerate the data - by calling ElementAt in this case.



                            Each time you enumerate the IEnumerable<string> object it runs the sequence of operations you specified, creating a random ordering of the elements. Each ElementAt(0) call will therefore return the first element of a new random sequence.



                            Essentially what you appear to be misunderstanding is this: an IEnumerable<T> is not a collection.



                            You can however convert the IEnumerable<string> to a collection using ToArray() or ToList(). These will take the output of the operation sequence specified by the IEnumerable<> and create a new collection - string or List<string> respectively.



                            For instance:



                            string collection = {"Zero", "One", "Two", "Three", "Four"};
                            var random = new Random();
                            var enumerableCollection = collection.OrderBy(e => random.NextDouble()).ToArray();

                            Console.WriteLine(enumerableCollection.ElementAt(0));
                            Console.WriteLine(enumerableCollection.ElementAt(0));
                            Console.WriteLine(enumerableCollection.ElementAt(0));
                            Console.WriteLine(enumerableCollection.ElementAt(0));
                            Console.WriteLine(enumerableCollection.ElementAt(0));


                            Now you'll get a random item from the original array, but it will be the same item multiple times. Instead of randomizing each time it's just reading the first item in a new collection whose order is randomized.






                            share|improve this answer












                            The simple answer is that you are specifically forcing a non-deterministic situation. The why is due to how LINQ functions.



                            At its core LINQ is designed around the concept of building objects that represent operations on a set of data - object, records, etc. - and then executing those operations at enumeration time. When you call OrderBy the return is an object that will process the origin to perform the ordering, not a new collection that is ordered. The order is Only when you actually enumerate the data - by calling ElementAt in this case.



                            Each time you enumerate the IEnumerable<string> object it runs the sequence of operations you specified, creating a random ordering of the elements. Each ElementAt(0) call will therefore return the first element of a new random sequence.



                            Essentially what you appear to be misunderstanding is this: an IEnumerable<T> is not a collection.



                            You can however convert the IEnumerable<string> to a collection using ToArray() or ToList(). These will take the output of the operation sequence specified by the IEnumerable<> and create a new collection - string or List<string> respectively.



                            For instance:



                            string collection = {"Zero", "One", "Two", "Three", "Four"};
                            var random = new Random();
                            var enumerableCollection = collection.OrderBy(e => random.NextDouble()).ToArray();

                            Console.WriteLine(enumerableCollection.ElementAt(0));
                            Console.WriteLine(enumerableCollection.ElementAt(0));
                            Console.WriteLine(enumerableCollection.ElementAt(0));
                            Console.WriteLine(enumerableCollection.ElementAt(0));
                            Console.WriteLine(enumerableCollection.ElementAt(0));


                            Now you'll get a random item from the original array, but it will be the same item multiple times. Instead of randomizing each time it's just reading the first item in a new collection whose order is randomized.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered 41 mins ago









                            Corey

                            10.5k12252




                            10.5k12252






























                                 

                                draft saved


                                draft discarded



















































                                 


                                draft saved


                                draft discarded














                                StackExchange.ready(
                                function () {
                                StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53348977%2fwhy-is-linq-non-deterministic%23new-answer', 'question_page');
                                }
                                );

                                Post as a guest















                                Required, but never shown





















































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown

































                                Required, but never shown














                                Required, but never shown












                                Required, but never shown







                                Required, but never shown







                                Popular posts from this blog

                                Costa Masnaga

                                Fotorealismo

                                Sidney Franklin