-3

How can you best explain why replacing an element of a collection you are looping using foreach is permited if you make a copy of it. Example:

foreach(Item item in Items)
{
   item.modify //or remove or add
}
// will not work

foreach(Item item in Items.ToList())
{
   item.modify //or remove. or add
}

//will work altough i dont get it because i am now iterating trough the temporary list
//and changing its elements. 
//In my understanding its not like im iterating the list(.ToList) and modifying the source items
//(Items). A graphic representation would be welcome, my interest is to understand the
//matter logically
Freeman
  • 5,691
  • 3
  • 29
  • 41
  • 2
    Because if you **make a copy of the list** then removing an item from the *original list* (which is *not* being iterated!) does not affect the copy. –  May 09 '12 at 06:48
  • you need to find the inner of the list and how the items connected together, and how the iterator move from one element to the other to understand why this is happening (beside the copy). The lists are connected together with pointers. When you remove an item from the list all the list change and the iterator can not be the same for the next loop. – Aristos May 09 '12 at 06:50
  • if it uses the list to iterate then logicaly it will use the same list to remove from. because im using the list object for this operation. – Freeman May 09 '12 at 06:51
  • @Aristos i tried even drawing the objects on paper represented in the stack and heap yet i could not come up with a logical representation. – Freeman May 09 '12 at 06:53
  • @Freeman see this draw http://en.wikipedia.org/wiki/Doubly_linked_list – Aristos May 09 '12 at 06:58
  • @Aristos. Thank you for the reply. I have studied algorithms and data structures on pluralsight and understand the concept(or so i think). What i dont understand if i use an object to iterate on(in my case the copied list) then modifying/deleting/adding an element should ocure in the same object used in the iteration.(the List). Is that correct, if not why? – Freeman May 09 '12 at 07:04
  • @Freeman the answer is given by the pst, you iterate the copy, but you delete the original. (its 2 different lists) – Aristos May 09 '12 at 07:26
  • @Freeman: you get a **copy** of the **list**, but not the copy of the **content** of the list (if we are talking about reference types). So if you copy a list and inside you have a reference types, bychnaging an object inside one you will change it also inside another cause it's the same reference. What make the difference is that you have a copy of the **list** strucutre and **not** its content – Tigran May 09 '12 at 07:31
  • dear Aristos, thank you for really trying to help. I understand that it deletes from the original, but the point of the question, it should not remove from the original, because you are making an action over an element of the list you are iterating. Unfortunately thats my dillema. – Freeman May 09 '12 at 07:32
  • @tigran your last comment made it a bit clear. but stil im in the fog. The original list and the copied list both have references in the stack pointing to only one value in the heap. I got that. Though if you change the value either from the list or the original collection both lists are affected thus changed. So in my mind you it would not be allowed to change any elements because you are working with a copy of the same object. – Freeman May 09 '12 at 07:46
  • @Freeman: the change is not possible **not** on the elements of the list, but on **list** itself. You can not Add/Remove elements to instance of the **list** you iterating over, cause you change a count elements and IEnumerator relay on this. But if you use simple for(i=0;..) construct, you can achieve what you want without making a copy, cause there is no any Enumerator alloation, but direct access to the elements of the list. – Tigran May 09 '12 at 07:50
  • That is exactly my point, if i remove an element from the 'ToList' it means i am removing it from the 'Items' also. That means that the count property of the IEnumerator changes for both lists, therefore it should be an ilegal operation regardless the object you are iterating on. Am i correct? – Freeman May 09 '12 at 08:03

3 Answers3

0

Because Enumerator relays on count of the elements in collection and you're not premitted to change it during the iteration.

If you make a copy of the list (responding to your question) you iterating over a copy of the collection you're changing. That is.

Tigran
  • 61,654
  • 8
  • 86
  • 123
  • i know that but then if you do a ToList() arent you doing the same operation on the list items this time, yet it has no problem of doing it. Why? – Freeman May 09 '12 at 06:48
  • @Freeman: ToList() makes a new **copy** of the list, that is. – Tigran May 09 '12 at 06:49
  • does it make a new copy of the list each time it iterates? – Freeman May 09 '12 at 06:55
  • 4
    and for the guys marking the question negative, if you cant answer it like a pro leave just leave it alone, im looking for help not for 'hey dude i know this question, its so simple i will not even bother answering, i will mark it negative though' – Freeman May 09 '12 at 07:27
  • @Freeman: in the code provided **no**. Even if you have it on in foreach loop definition line, it will be created only ones. .NET is clever enough to manage this. – Tigran May 09 '12 at 07:29
  • @Freeman, I have upped your question. I have found that this forum is a rather snobbish one, where lots of energy is spent patroling the posts when they could be better spent *understanding* them. Most of the time, the merit of a question is decided based on the reputation of the poster, and not the question itself. I hope you get to read this before the SO Police take it down. – Old Geezer May 11 '12 at 09:55
  • @OldGeezer: to be clear, I didn't downvoted you, but even upvoted. – Tigran May 11 '12 at 09:58
  • Thank you OldGeezer, i am not 100% sure about my answer, but its the only possible scenario, because ive tested the iteration in a list created explicitly by me and never throws an exception even if i remove an item from it. And dont worry about trolls, i know most of them did not even bother to understand the real problem before posting comments. – Freeman May 11 '12 at 13:30
  • @Freeman I agree with Old Geezer. I upvoted your question and I find it a shame that there are so many snobs in SO. – David Klempfner Dec 11 '18 at 04:40
-1

The Best answer would be that List has some kind of Tracking over its list items and can update its items as you ask but a simple IEnumerable does not so it will not allow you to change them.

Freeman
  • 5,691
  • 3
  • 29
  • 41
-1

What type is your Items? What does the modify method do? I could not reproduce what you could do with the second option. I cannot compile this:

int[] nn = new int[] { 1, 2 };
foreach (var n in nn.ToList())
   n++;

Error: Cannot assign to 'n' because it is a 'foreach iteration variable'

Old Geezer
  • 14,854
  • 31
  • 111
  • 198
  • my items are of type EntityObject . so on a collection i use IEnumerable in my case IEnumerable . – Freeman May 13 '12 at 16:39