So I've been trying to implement a quicksort myself, just to learn something from it, but it also generates a stackoverflowexception, but I can't seem to find what the cause is.
Can someone give me a clue?
public void Partition(List<int> valuelist, out List<int> greater, out List<int> lesser)
{
lesser = new List<int>(); // <-- Stackoverflow exception here!
greater = new List<int>();
if (valuelist.Count <= 1)
return;
pivot = valuelist.First();
foreach (int Element in valuelist)
{
if (Element <= pivot)
lesser.Add(Element);
else
greater.Add(Element);
}
}
public List<int> DoQuickSort(List<int> list)
{
List<int> great;
List<int> less;
Partition(list, out great, out less);
DoQuickSort(great);
DoQuickSort(less);
list.Clear();
list = (List<int>)less.Concat(great);
return list;
}
you are doing an infinite loop right there
DoQuickSort(great);
you need a way to get out of that loop with a flag or a condition
Edit
I will add that in debugging mode, with default setting, you can only reach between 10,000 and 16,000 recursive call before an exception is thrown and between 50,000 and 80,000 when in release mode, all depend on the actual code executed.
If you play with a huge number of values, you might need to manage yourself that recursive call by using a Stack object.
sample code to see how much call before it crash;
(debug; 14,210 call, release 80,071 call)
static int s = 1;
static void Main(string[] args)
{
o();
}
static void o()
{
s++;
Console.WriteLine(s.ToString());
o();
}
You're not putting any conditions on your recursive calls to DoQuicksort, so it'll never stop recursing, leading to a stack overflow. You should only be calling DoQuicksort on a list if it contains more than one element.
Edit: As Will said in his comment, this is a very slow approach to "Quicksort". You should look at in-place partitioning algorithms, as mentioned on Wikipedia's Quicksort article.
I think one of the problems in your code that you keep the pivot value when partitioning the list. This means that you will run into a situation where all values partition into either greater or less, and the partitioning will stop working. This will effectively not letting you split one of the lists anylonger, so the exit condition in the Partition method is never satisfied.
You should select a pivot value, remove the pivot element from the list (this part is missing in your code), parition it in greater and less lists, sort those (recursively), and then concatenate the less list, the pivot element (this is also, naturally, missing in your code) and the greater list.
I can post an updated, working, code sample, but since you are in "learning mode", I will keep it to myself until you ask for it :)
Related
I recently came across an issue where I was able to change the IEnumerable object that I was iterating over in a foreach loop. It's my understanding that in C#, you aren't supposed to be able to edit the list you're iterating over, but after some frustration, I found that this is exactly what was happening. I basically looped through a LINQ query and used the object IDs to make changes in the database on those objects and those changes affected the values in the .Where() statement.
Does anybody have an explanation for this? It seems like the LINQ query re-runs every time it's iterated over
NOTE: The fix for this is adding .ToList() after the .Where(), but my question is why this issue is happening at all i.e. if it's a bug or something I'm unaware of
using System;
using System.Linq;
namespace MyTest {
class Program {
static void Main () {
var aArray = new string[] {
"a", "a", "a", "a"
};
var i = 3;
var linqObj = aArray.Where(x => x == "a");
foreach (var item in linqObj ) {
aArray[i] = "b";
i--;
}
foreach (var arrItem in aArray) {
Console.WriteLine(arrItem); //Why does this only print out 2 a's and 2 b's, rather than 4 b's?
}
Console.ReadKey();
}
}
}
This code is just a reproducible mockup, but I'd expect it to loop through 4 times and change all of the strings in aArray into b's. However, it only loops through twice and turns the last two strings in aArray into b's
EDIT: After some feedback and to be more concise, my main question here is this: "Why am I able to change what I'm looping over as I'm looping over it". Looks like the overwhelming answer is that LINQ does deferred execution, so it's re-evaluating as I'm looping through the LINQ IEnumerable.
EDIT 2: Actually looking through, it seems that everyone is concerned with the .Count() function, thinking that is what the issue here is. However, you can comment out that line and I still have the issue of the LINQ object changing. I updated the code to reflect the main issue
Why am I able to edit a LINQ list while iterating over it?
All of the answers that say that this is because of deferred "lazy" execution are wrong, in the sense that they do not adequately address the question that was asked: "Why am I able to edit a list while iterating over it?" Deferred execution explains why running the query twice gives different results, but does not address why the operation described in the question is possible.
The problem is actually that the original poster has a false belief:
I recently came across an issue where I was able to change the IEnumerable object that I was iterating over in a foreach loop. It's my understanding that in C#, you aren't supposed to be able to edit the list you're iterating over
Your understanding is wrong, and that's where the confusion comes from. The rule in C# is not "it is impossible to edit an enumerable from within an enumeration". The rule is you are not supposed to edit an enumerable from within an enumeration, and if you choose to do so, arbitrarily bad things can happen.
Basically what you're doing is running a stop sign and then asking "Running a stop sign is illegal, so why did the police not prevent me from running the stop sign?" The police are not required to prevent you from doing an illegal act; you are responsible for not making the attempt in the first place, and if you choose to do so, you take the chance of getting a ticket, or causing a traffic accident, or any other bad consequence of your poor choice. Usually the consequences of running a stop sign are no consequences at all, but that does not mean that it's a good idea.
Editing an enumerable while you're enumerating it is a bad practice, but the runtime is not required to be a traffic cop and prevent you from doing so. Nor is it required to flag the operation as illegal with an exception. It may do so, and sometimes it does do so, but there is not a requirement that it does so consistently.
You've found a case where the runtime does not detect the problem and does not throw an exception, but you do get a result that you find unexpected. That's fine. You broke the rules, and this time it just happens that the consequence of breaking the rules was an unexpected outcome. The runtime is not required to make the consequence of breaking the rules into an exception.
If you tried to do the same thing where, say, you called Add on a List<T> while enumerating the list, you'd get an exception because someone wrote code in List<T> that detects that situation.
No one wrote that code for "linq over an array", and so, no exception. The authors of LINQ were not required to write that code; you were required to not write the code you wrote! You chose to write a bad program that violates the rules, and the runtime is not required to catch you every time you write a bad program.
It seems like the LINQ query re-runs every time it's iterated over
That is correct. A query is a question about a data structure. If you change that data structure, the answer to the question can change. Enumerating the query answers the question.
However, that is an entirely different issue than the one in the title of your question. You really have two questions here:
Why can I edit an enumerable while I am enumerating it?
You can do this bad practice because nothing stops you from writing a bad program except your good sense; write better programs that do not do this!
Does a query re-execute from scratch every time I enumerate it?
Yes; a query is a question, not an answer. An enumeration of the query is an answer, and the answer can change over time.
The explanation to your first question, why your LINQ query re-runs every time it's iterated over is because of Linq's deferred execution.
This line just declares the linq exrpession and does not execute it:
var linqLIST = aArray.Where(x => x == "a");
and this is where it gets executed:
foreach (var arrItem in aArray)
and
Console.WriteLine(linqList.Count());
An explict call ToList() would run the Linq expression immediately. Use it like this:
var linqList = aArray.Where(x => x == "a").ToList();
Regarding the edited question:
Of course, the Linq expression is evaluated in every foreach iteration. The issue is not the Count(), instead every call to the LINQ expression re-evaluates it. As mentioned above, enumerate it to a List and iterate over the list.
Late edit:
Concerning #Eric Lippert's critique, I will also refer and go into detail for the rest of the OP's questions.
//Why does this only print out 2 a's and 2 b's, rather than 4 b's?
In the first loop iteration i = 3, so after aArray[3] = "b"; your array will look like this:
{ "a", "a", "a", "b" }
In the second loop iteration i(--) has now the value 2 and after executing aArray[i] = "b"; your array will be:
{ "a", "a", "b", "b" }
At this point, there are still a's in your array but the LINQ query returns IEnumerator.MoveNext() == false and as such the loop reaches its exit condition because the IEnumerator internally used, now reaches the third position in the index of the array and as the LINQ is re-evaluated it doesn't match the where x == "a" condition any more.
Why am I able to change what I'm looping over as I'm looping over it?
You are able to do so because the build in code analyser in Visual Studio is not detecting that you modify the collection within the loop. At runtime the array is modified, changing the outcome of the LINQ query but there is no handling in the implementation of the array iterator so no exception is thrown.
This missing handling seems by design, as arrays are of fixed size oposed to lists where such an exception is thrown at runtime.
Consider following example code which should be equivalent with your initial code example (before edit):
using System;
using System.Linq;
namespace MyTest {
class Program {
static void Main () {
var aArray = new string[] {
"a", "a", "a", "a"
};
var iterationList = aArray.Where(x => x == "a").ToList();
foreach (var item in iterationList)
{
var index = iterationList.IndexOf(item);
iterationList.Remove(item);
iterationList.Insert(index, "b");
}
foreach (var arrItem in aArray)
{
Console.WriteLine(arrItem);
}
Console.ReadKey();
}
}
}
This code will compile and iterate the loop once before throwing an System.InvalidOperationException with the message:
Collection was modified; enumeration operation may not execute.
Now the reason why the List implementation throws this error while enumerating it, is because it follows a basic concept: For and Foreach are iterative control flow statements that need to be deterministic at runtime. Furthermore the Foreach statement is a C# specific implementation of the iterator pattern, which defines an algorithm that implies sequential traversal and as such it would not change within the execution. Thus the List implementation throws an exception when you modify the collection while enumerating it.
You found one of the ways to modify a loop while iterating it and re-eveluating it in each iteration. This is a bad design choice because you might run into an infinite loop if the LINQ expression keeps changing the results and never meets an exit condition for the loop. This will make it hard to debug and will not be obvious when reading the code.
In contrast there is the while control flow statement which is a conditional construct and is ment to be non-deterministic at runtime, having a specific exit condition that is expected to change while execution.
Consider this rewrite base on your example:
using System;
using System.Linq;
namespace MyTest {
class Program {
static void Main () {
var aArray = new string[] {
"a", "a", "a", "a"
};
bool arrayHasACondition(string x) => x == "a";
while (aArray.Any(arrayHasACondition))
{
var index = Array.FindIndex(aArray, arrayHasACondition);
aArray[index] = "b";
}
foreach (var arrItem in aArray)
{
Console.WriteLine(arrItem); //Why does this only print out 2 a's and 2 b's, rather than 4 b's?
}
Console.ReadKey();
}
}
}
I hope this should outline the technical background and explain your false expectations.
Enumerable.Where returns an instance that represents a query definition. When it is enumerated*, the query is evaluted. foreach allows you to work with each item at the time it is found by the query. The query is deferred, but it also pause-able/resume-able, by the enumeration mechanisms.
var aArray = new string[] { "a", "a", "a", "a" };
var i = 3;
var linqObj = aArray.Where(x => x == "a");
foreach (var item in linqObj )
{
aArray[i] = "b";
i--;
}
At the foreach loop, linqObj is enumerated* and the query is started.
The first item is examined and a match is found. The query is paused.
The loop body happens: item="a", aArray[3]="b", i=2
Back to the foreach loop, the query is resumed.
The second item is examined and a match is found. The query is paused.
The loop body happens: item="a", aArray[2]="b", i=2
Back to the foreach loop, the query is resumed.
The third item is examined and is "b", not a match.
The fourth item is examined and is "b", not a match.
The loop exits and the query concludes.
Note: is enumerated* : this means GetEnumerator and MoveNext are called. This does not mean that the query is fully evaluated and results held in a snapshot.
For further understanding, read up on yield return and how to write a method that uses that language feature. If you do this, you'll understand what you need in order to write Enumerable.Where
IEnumerable in c# is lazy. This means whenever you force it to evaluate you get the result. In your case Count() forces the linqLIST to evaluate every time you call it. by the way, linqLIST is not a list right now
You could upgrade the «avoid side-effects while enumerating an array» advice to a requirement, by utilizing the extension method below:
private static IEnumerable<T> DontMessWithMe<T>(this T[] source)
{
var copy = source.ToArray();
return source.Zip(copy, (x, y) =>
{
if (!EqualityComparer<T>.Default.Equals(x, y))
throw new InvalidOperationException(
"Array was modified; enumeration operation may not execute.");
return x;
});
}
Now chain this method to your query and watch what happens. 😃
var linqObj = aArray.DontMessWithMe().Where(x => x == "a");
Of course this comes with a cost. Now every time you enumerate the array, a copy is created. This is why I don't expect that anyone will use this extension, ever!
Basically I am wondering if it's ok to use an enumeration more than once in code subsequently. Whether you break early or not, would the enumeration always reset in every foreach case below, so giving us consistent enumeration from start to end of the effects collection?
var effects = this.EffectsRecursive;
foreach (Effect effect in effects)
{
...
}
foreach (Effect effect in effects)
{
if(effect.Name = "Pixelate")
break;
}
foreach (Effect effect in effects)
{
...
}
EDIT: The implementation of EffectsRecursive is this:
public IEnumerable<Effect> Effects
{
get
{
for ( int i = 0; i < this.IEffect.NumberOfChildren; ++i )
{
IEffect effect = this.IEffect.GetChildEffect ( i );
if ( effect != null )
yield return new Effect ( effect );
}
}
}
public IEnumerable<Effect> EffectsRecursive
{
get
{
foreach ( Effect effect in this.Effects )
{
yield return effect;
foreach ( Effect seffect in effect.ChildrenRecursive )
yield return seffect;
}
}
}
Yes this is legal to do. The IEnumerable<T> pattern is meant to support multiple enumerations on a single source. Collections which can only be enumerated once should expose IEnumerator instead.
The code that consumes the sequence is fine. As spender points out, the code that produces the enumeration might have performance problems if the tree is deep.
Suppose at the deepest point your tree is four deep; think about what happens on the nodes that are four deep. To get that node, you iterate the root, which calls an iterator, which calls an iterator, which calls an iterator, which passes the node back to code that passes the node back to code that passes the node back... Instead of just handing the node to the caller, you've made a little bucket brigade with four guys in it, and they're tramping the data around from object to object before it finally gets to the loop that wanted it.
If the tree is only four deep, no big deal probably. But suppose the tree is ten thousand elements, and has a thousand nodes forming a linked list at the top and the remaining nine thousand nodes on the bottom. Now when you iterate those nine thousand nodes each one has to pass through a thousand iterators, for a total of nine million copies to fetch nine thousand nodes. (Of course, you've probably gotten a stack overflow error and crashed the process as well.)
The way to deal with this problem if you have it is to manage the stack yourself rather than pushing new iterators on the stack.
public IEnumerable<Effect> EffectsNotRecursive()
{
var stack = new Stack<Effect>();
stack.Push(this);
while(stack.Count != 0)
{
var current = stack.Pop();
yield return current;
foreach(var child in current.Effects)
stack.Push(child);
}
}
The original implementation has a time complexity of O(nd) where n is the number of nodes and d is the average depth of the tree; since d can in the worst case be O(n), and in the best case be O(lg n), that means that the algorithm is between O(n lg n) and O(n^2) in time. It is O(d) in heap space (for all the iterators) and O(d) in stack space (for all the recursive calls.)
The new implementation has a time complexity of O(n), and is O(d) in heap space, and O(1) in stack space.
One down side of this is that the order is different; the tree is traversed from top to bottom and right to left in the new algorithm, instead of top to bottom and left to right. If that bothers you then you can just say
foreach(var child in current.Effects.Reverse())
instead.
For more analysis of this problem, see my colleague Wes Dyer's article on the subject:
http://blogs.msdn.com/b/wesdyer/archive/2007/03/23/all-about-iterators.aspx
Legal, yes. Whether it will function as you expect depends on:
The implementation of the IEnumerable returned by EffectsRecursive and whether it always returns the same set;
Whether you want to enumerate the same set both times
If it returns an IEnumerable that requires some intensive work, and it doesn't cache the results internally, then you may need to .ToList() it yourself. If it does cache the results, then ToList() would be slightly redundant but probably no harm.
Also, if GetEnumerator() is implemented in a typical/proper (*) way, then you can safely enumerate any number of times - each foreach will be a new call to GetEnumerator() which returns a new instance of the IEnumerator. But it could be that in some situations it returns the same IEnumerator instance that's already been partially or fully enumerated, so it all really just depends on the specific intended usage of that particular IEnumerable.
*I'm pretty sure returning the same enumerator multiple times is actually a violation of the implied contract for the pattern, but I have seen some implementations that do it anyway.
Most probably, yes. Most implementations of IEnumerable return a fresh IEnumerator which starts at the beginning of the list.
It all depends on the implementation of the type of EffectsRecursive.
I'm learning the basics of programming here (C#) but I think this question is generic in its nature.
What are some simple practical situations that lend themselves closer to a particular type of loop?
The while and for loops seem pretty similar and there are several SO questions addressing the differences between the two. How about foreach? From my basic understanding, its seems I ought to be able to do everything a foreach loop does within a for loop.
Which ever works best for code readability. In other words use the one that fits the situation best.
while: When you have a condition that needs to be checked at the start of each loop. e.g. while(!file.EndOfFile) { }
for: When you have an index or counter you are incrementing on each loop. for (int i = 0; i<array.Length; i++) { }. Essentially, the thing you are looping over is an indexable collection, array, list, etc.
foreach: When you are looping over a collection of objects or other Enumerable. In this event you may not know (or care) the size of the collection, or the collection is not index based (e.g. a set of objects). Generally I find foreach loops to be the most readable when I'm not interested in the index of something or any other exit conditions.
Those are my general rules of thumb anyway.
1. foreach and for
A foreach loop works with IEnumerator, when a for loop works with an index (in object myObject = myListOfObjects[i], i is the index).
There is a big difference between the two:
an index can access directly any object based on its position within a list.
an enumerator can only access the first element of a list, and then move to the next element (as described in the previous link from the msdn). It cannot access an element directly, just knowing the index of the element within a list.
So an enumerator may seem less powerful, but:
you don't always know the position of elements in a group, because all groups are not ordered/indexed.
you don't always know the number of elements in a list (think about a linked list).
even when it's ordered, the indexed access of a list may be based internally on an enumerator, which means that each time you're accessing an element by its position you may be actually enumerating all elements of the list up until the element you want.
indexes are not always numeric. Think about Dictionary.
So actually the big strength of the foreach loop and the underlying use of IEnumerator is that it applies to any type which implements IEnumerable (implementing IEnumerable just means that you provide a method that returns an enumerator). Lists, Arrays, Dictionaries, and all other group types all implement IEnumerable. And you can be sure that the enumerator they have is as good as it gets: you won't find a fastest way to go through a list.
So, the for loop can generally be considered as a specialized foreach loop:
public void GoThrough(List<object> myList)
{
for (int i=0; i<myList.Count; i++)
{
MessageBox.Show(myList[i].ToString());
}
}
is perfectly equivalent to:
public void GoThrough(List<object> myList)
{
foreach (object item in myList)
{
MessageBox.Show(item.ToString());
}
}
I said generally because there is an obvious case when the for loop is necessary: when you need the index (i.e. the position in the list) of the object, for some reason (like displaying it). You will though eventually realize that this happens only in specific cases when you do good .NET programming, and that foreach should be your default candidate for loops over a group of elements.
Now to keep comparing the foreach loop, it is indeed just an eye-candy specific while loop:
public void GoThrough(IEnumerable myEnumerable)
{
foreach (object obj in myEnumerable)
{
MessageBox.Show(obj.ToString());
}
}
is perfectly equivalent to:
public void GoThrough(IEnumerable myEnumerable)
{
IEnumerator myEnumerator = myEnumerable.GetEnumerator();
while (myEnumerator.MoveNext())
{
MessageBox.Show(myEnumerator.Current.ToString());
}
}
The first writing is a lot simpler though.
2. while and do..while
The while (condition) {action} loop and the do {action} while (condition) loop just differ from each other by the fact that the first one tests the condition before applying the action, when the second one applies the action, then tests the condition. The do {..} while (..) loop is used quite marginally compared to the others, since it runs the action at least once even if the condition is initially not met (which can lead to trouble, since the action is generally dependent on the condition).
The while loop is more general than the for and foreach ones, which apply specifically to lists of objects. The while loop just has a condition to go on, which can be based on anything. For example:
string name = string.empty;
while (name == string.empty)
{
Console.WriteLine("Enter your name");
name = Console.ReadLine();
}
asks the user to input his name then press Enter, until he actually inputs something. Nothing to do with lists, as you can see.
3. Conclusion
When you are going through a list, you should use foreach unless you need the numeric index, in which case you should use for.
When it doesn't have anything to do with list, and it's just a procedural construction, you should use while(..) {..}.
Now to conclude with something less restrictive: your first goal with .NET should be to make your code readable/maintainable and make it run fast, in that order of priority. Anything that achieves that is good for you. Personally though, I think the foreach loop has the advantage that potentially, it's the most readable and the fastest.
Edit: there is an other case where the for loop is useful: when you need indexing to go through a list in a special way or if you need to modify the list when in the loop. For example, in this case because we want to remove every null element from myList:
for (int i=myList.Count-1; i>=0; i--)
{
if (myList[i] == null) myList.RemoveAt(i);
}
You need the for loop here because myList cannot be modified from within a foreach loop, and we need to go through it backwards because if you remove the element at the position i, the position of all elements with an index >i will change.
But the use for these special constructions have been reduced since LINQ. The last example can be written like this in LINQ for example:
myList.RemoveAll(obj => obj == null);
LINQ is a second step though, learn the loops first.
when you know how many iterations there will be use for
when you don't know use while, when don't know and need to execute code at least once use do
when you iterate through collection and don't need index use foreach
(also you can not use collection[i] on everything that you can use foreach on)
As others have said, 'it depends'.
I find I use simple 'for' loops very rarely nowadays. If you start to use Linq you'll find you either don't need loops at all and when you do it's the 'foreach' loop that's called for.
Ultimately I agree with Colin Mackay - code for readability!
The do while loop has been forgotten, I think :)
Taken from here.
The C# while statement executes a statement or a block of statements until a specified expression evaluates to false . In some situation you may want to execute the loop at least one time and then check the condition. In this case you can use do..while loop.
The difference between do..while and while is that do..while evaluates its expression at the bottom of the loop instead of the top. Therefore, the statements within the do block are always executed at least once. From the following example you can understand how do..while loop function.
using System;
using System.Windows.Forms;
namespace WindowsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int count = 5;
do{
MessageBox.Show(" Loop Executed ");
count++;
}while (count <=4);
}
private void button2_Click(object sender, EventArgs e)
{
int count = 5;
while (count <=4){
MessageBox.Show(" Loop Executed ");
count++;
}
}
}
}
If you have a collection and you kow upfront you're going to systematically pass through all values, use foreach as it is usually easier to work with the "current" instance.
If some condition can make you stop iterating, you can use for or while. They are pretty similar, the big difference being that for takes control of when the current index or value is updated (in the for declaration) as in a while you decide when and where in the while block to update some values that are then checked in the while predicate.
If you are writing a parser class, lets say an XMLParser that will read XML nodes from a given source, you can use while loop as you don't know how many tags are there.
Also you can use while when you iterate if the variable is true or not.
You can use for loop if you want to have a bit more control over your iterations
I cannot figure this out. The workflow of passing IEnumerable<T> (T is some my class, but it is not relevant here) basically looks like this:
var a = GetEntireCollection(); // so I get IEnumerable<T>
...
var b = a.Where(condition1);
...
var c = b.Where(condition2);
...
So I filter out more and more items from the collection, finally I call:
if (z.IsEmpty())
throw new Exception();
Foo(z);
and Foo is
public void Foo(IEnumerable<T> p)
{
pool = p.OrderByDescending(it => it.MyProperty).ToList();
if (pool.IsEmpty())
throw new Exception(pool.Count().ToString() + ", " + p.Count().ToString());
...
All I do, is order the collection.
Now, my program crashes with exception -- it says that p has Count = 1, and pool has Count = 0. What's more when I point out p and require the results (I run program using Visual Studio) it says, the collection yielded with no results (or somethig similar, not verbatim quote).
Questions:
how can non-empty collection become empty just by reordering?
how can collection Count can be > 0, when there are no items in it?
I am asking because I would like to know how to avoid this situation, but honestly, when I am looking at the code it seems 100% legit for me.
Technical background:
it is pure C# code, no asm inlines, or anything like this
no threads
no external libraries, except for Where (which comes from Linq) this is all my code
Edits
Edit 1
public static bool IsEmpty<T>(this IEnumerable<T> coll)
{
var iter = coll.GetEnumerator();
return !iter.MoveNext();
}
Edit 2
Just before I call Foo(z) I check if the z is empty, so the code looks like this:
if (z.IsEmpty())
throw new Exception();
Foo(z);
SOLVED
As Jon suggested (C# sharpshooting I would say) one of the conditions was time dependent. So when the collection evaluation was forced the condition changed and I get in fact another collection.
One possibility is that evaluating the conditions twice is effectively changing the results.
Each time you iterate through p, it will re-evaluate the data, including the Where clauses. So you're doing that once to populate pool, and then again to print out p.Count().
Without any more information about what GetEntireCollection does or what the Where conditions are, it's hard to say what's going on... but that's one possible explanation. If you can post a short but complete program demonstrating the problem, that would help a lot.
It's empty because of Deferred Execution, most query operators execute not when
constructed, but when enumerated (in other words, when MoveNext is called on its
enumerator).
So if you change it to :
var c = b.Where(condition2).ToList();
And then call Foo(c) it will work.
I think the code you show will call GetEntireCollection multiple times.
So maybe this method is returning different results on successive invocations.
I've recently been implementing a recursive directory search implementation and I'm using a Stack to track the path elements. When I used string.Join() to join the path elements, I found that they were reversed. When I debugged the method, I looked into the stack and found that the elements themselves were reversed in the Stack's internal array, ie the most recently Push()ed element was at the beginning of the internal array, and the least recently Push()ed element was at the end of the internal array. This seems ass-backward and very counter-intuitive. Can somebody please tell me why Microsoft would implement a stack in such a manner ?
I think you're mistaken.
It isn't that Stack<T>.Push internally inserts an item at the start of its internal array (it doesn't). Rather, it enumerates from the top to the bottom, as this is the manner in which one would intuitively enumerate through a stack (think of a stack of pancakes: you start at the top and work your way down).
If you look at the contents of a collection from within Visual Studio's debugger, I think it will display them to you in the order they're enumerated -- not the order they're stored internally*.
Take a look at the Stack<T>.Push method in Reflector and you'll see that the code is basically exactly what you'd expect:
// (code to check array size)
this._array[this._size++] = item;
// (code to update internal version number)
So the stack internally adds new elements onto the end of its internal array. It's the Stack<T>.Enumerator class that's got you confused, not the Stack<T> class itself.
*I don't know whether this is true in general, but it's true for Stack<T>; see Hans Passant's excellent answer for the reason why.
You had me going there for a bit, that indeed looks completely bass-ackwards. There is however something else going on. The Stack<> class has a debugger visualizer, named System_StackDebugView<>. It is an internal class, you'd have to look with Reflector to see it.
That visualizer has an Items property, that's what you look at when you expand the node in the debugger. That Items property uses Stack<>.ToArray(). Which looks like this:
public T[] ToArray()
{
T[] localArray = new T[this._size];
for (int i = 0; i < this._size; i++)
{
localArray[i] = this._array[(this._size - i) - 1];
}
return localArray;
}
Yup, backwards.
What you described is the correct implementation, as a stack is a LIFO (Last in First out) structure. Imagine it like a stack of plates, the most recently element placed into the stack is the first one removed. Have you run into a stack elsewhere that is FIFO?
FIFO would be a Queue.
Here is how the stack's push and pops methods are implemented. Notice that it is using the last index in the array, rather than the first. So there must be some other problem going on to get yours backwards.
public virtual void Push(object obj)
{
if (this._size == this._array.Length)
{
object[] destinationArray = new object[2 * this._array.Length];
Array.Copy(this._array, 0, destinationArray, 0, this._size);
this._array = destinationArray;
}
this._array[this._size++] = obj;
this._version++;
}
public virtual object Pop()
{
if (this._size == 0)
{
throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_EmptyStack"));
}
this._version++;
object obj2 = this._array[--this._size];
this._array[this._size] = null;
return obj2;
}
To add to the other answers, if in the debugger you scroll down to the bottom of your Stack<>'s elements and open up Raw View->Non-Public members->_array you can see the contents of the actual internal array used to hold the items and verify that they are in the expected order.
I don't see what it matters which end they consider the top of the stack, as long as you now know which end it is. It actually makes more sense that when you 'push' something on to the stack, you're pushing it on the top (beginning) and moving the other items down...