Click here to Skip to main content
15,891,375 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Does anyone knows why the length after leaving the while loop body in the below code is zero?

C#
static void Main(string[] args)
		{

			var list = new List<int>();
			for (int i = 0; i < 1000; i++)
			{
				list.Add(i);
			}

			var chunks = new List<IEnumerable<int>>();

			while (list.Count > 0)
			{
				chunks.Add(list.Take(10));
				list.RemoveRange(0, 10);
			}

			int length = chunks.ToList()[0].Count();
		}


What I have tried:

I tried to chunk a list into a specific segments.
Posted
Updated 9-Oct-18 2:54am
Comments
Aydin Homay 9-Oct-18 8:20am    
Please do not provide me chunking algorithm I already aware of several such algorithms and I know how to solve this problem. My question is only about the wired behavior of RemoverRange or perhaps Take.

1 solution

Linq is not magic - it works by deferred execution.
If you use the debugger, and put a breakpoint at the end of the while loop, the first time it hits it you look at chunks and it has one member - expanding the results view gives you not what you expected: 10, 11, .. 18, 19 instead of 0, 1, ... 8, 9
Run the loop again, and it gets even less what you wanted: two elements (correct) but expand either and they are both the same: 20, 21, 22, ... 28, 29
Why? Because the execution of the Take is deferred until your code attempts to use the results and by then, the source collection is empty.
So each evaluation you try to get the length gives "Enumeration yielded no results" and a length of zero.

You can do this and get the result you wanted:
chunks.Add(list.Take(10).ToList());
Because the ToList evaluates the Take immediately.

[edit] Typos.
And this: You do realize what RemoveRange actually does? And that you are using it in the least efficient way possible? Have a look at this: List<T> - Is it really as efficient as you probably think?[^] and you will see why.
[/edit]
 
Share this answer
 
v3
Comments
Aydin Homay 10-Oct-18 4:21am    
About the use of RemoveRange yes you are right but what is your suggestion if the sort of list is important to stay as it is. In any case you will have pointer correction cost.
OriginalGriff 10-Oct-18 4:31am    
"In any case you will have pointer correction cost."
Lists don't use pointers...
Aydin Homay 10-Oct-18 4:35am    
I think in side of List is an array and array deals with pointers.
OriginalGriff 10-Oct-18 4:46am    
Follow the link - it explains why what you are doing is horribly inefficient, regardless of pointer use in the generated IL - the actual pointer code for an array access is two very short lines of code!
Aydin Homay 10-Oct-18 7:33am    
I know what you are talking about on that link. But my question is what is your suggestion? When there is no issue regarding to memory as I am not developing for an embedded system (even C# .Net is not supposed for such use) and I got enough hardware to handle relatively heavy operations. I just need to keep the order of list as it is and process with the rest of functionality.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900