Really enjoyed the riddle and the explanation! Small correction, though, to avoid another bug. Enumerable.Range does not take a start and an end index but instead a start index and a count. So only if the start index is 0, this happens to be to be the end index + 1.
I think, that in second example the actual object that is being assigned to IEnumerable<Task> is Array<Task> which has its own implementation of Count(), that is not being re-enumerated second time.
That's a well done explanation and will help a lot of folk. Thank you for taking the time to put this together. Threading and all the weird race conditions, etc., that come along with it was my life for 5+ years up until a year ago. I diagnosed so many bugs in other dev's code caused by misunderstandings of a similar nature to the one in this riddle that it was disturbing - and these weren't inexperienced devs. Thankfully for the work I had to do async wasn't of much use but I sure did learn, sometimes painfully, the ins and outs of using Task ;) But that's all somebody else's problem now. 🙂
Great video, never knew that enum.count() would re enumerate the enumerable if it was already enumerated in the previous line!!!
This is a cool dynamic. I understand the answer for using the array instead gives "**2 stars!". This is happening because the Count() method has a couple of validations to try to avoid to enumerate the enumerable. So it's checking if the source has a property that has the quantity of elements and return it. Array is an ICollection so it has a Count property.
For the 2nd riddle, because the enumerable this time is an array of tasks, the Count() function is smart enough to use the fixed size of the array instead of re-iterating an enumerable with side effects. The code becomes deterministic. The array contains 2 completed tasks, and the output is "**2 Tasks completed!"
The answer is "**" followed by any possible interleaving of characters of "**" and "2 stars!" To be precise...
Excellent video! I hope to see you dissecting more of those challenges 👏
I love such riddles. And to get a video solution, was much more, than i excepted.👍 Its good to train or refresh such stuff, cause with all that syntactic sugar, its still important to know, what's under the hood. More riddles, do it, just do it. DO IT🤙
Haven't watched the video yet (paused at 0:11), but I'm going to guess: 1: it's not going to run syncronously because the select statement isn't evaluated before WhenAll is executed, but also because Console.Write isn't asyncronous. 2: tasks.Count() uses the linq count, which just enumerates the enumerable to count it, which will return 0 because it's already been evaluated. Not sure if I'm mixing up IEnumerable and IEnumerator here. EDIT: Oh, task is threaded, not asynchronous, got them mixed up. Then there's gonna be a race condition yea. Also guess I did mix up IEnumerable and IEnumerator.
I love this format!
I am using Visual Studio and running it in windows machine. The output at 8:57 when executed after using delay and asynchronous await, still my output is **2 stars!** and not **2 stars!. I am confused. Is it different in different OS. I see yours is Mac OS
Great explanation, I would like to know whats is the tool that you use to underline and draw the arrows?
Beware Count() - there be dragons! I highly recommend people actually look at the code inside of the Count() function. It is extremely important. Only way you will fully understand this extremely important and easy-to-misuse function.
Once I made a property initialization like this Prop => new Something(); instead of Prop { get; } = new Something(); and stuck in debugging of my program for two days 😅 The lesson is don't use fancy lambdas when you create objects unless you want to confuse anyone who reads your code.
Mind blowing! The best spent 11 minutes! :) Such a great example! :)
Threadpool. Deadpool's cousin who is not only aware that he's in a comic, but also that it's an online comic and knows how to screw with his universe using http requests.
At 7:06 you say that we continue not necessarily on the main thread, this is a bit confusing to me as the execution should sync back to the calling thread upon await, and we can avoid this behavior with an explicit ConfigureAwait(false) statement. Right ?
I don't use C# a lot so I didn't know about the second enumeration, and I've never used C# tasks before. But the fact that you had results with four stars in the poll options gave away the punch line -- I know threadpools so I knew there was a race condition there.
@amantinband