Skip to content

Instantly share code, notes, and snippets.

@theredpea
Created May 16, 2014 20:22
Show Gist options
  • Save theredpea/7dc62e93d641226e91ce to your computer and use it in GitHub Desktop.
Save theredpea/7dc62e93d641226e91ce to your computer and use it in GitHub Desktop.
ModifyingWhileIterating
//I couldn't figure out why I modified a List but later in the code the List seemed unchanged.
//I was modifying something returned the public accessor { get };
//But wasn't truly changing the private variable behind the public variable
//Again I ran into it while trying to fix TT0263356
void Main()
{
List<List<Ref>> Refss = new List<List<Ref>>{
new List<Ref> {
new Ref()
}
};
foreach(List<Ref> Refs in Refss)
{
foreach(Ref r in Refs)
{
r.startString="modified List<List<Ref>>";
}
}
Console.WriteLine(Refss[0][0].startString);
ListRef lr = new ListRef(){ Refs = new List<Ref> { new Ref() } };
foreach(Ref r in lr.Refs)
{
//ModifyRef(r);
r.startString="modified ListRef()'s Refs (a List<Ref>)";
}
Console.WriteLine(lr.Refs[0].startString);
ListRefImplicitSetter lris = new ListRefImplicitSetter();
foreach(Ref r in lris.Refs)
{
//ModifyRef(r);
r.startString="modified ListRefImplicitSetter()'s Refs (a List<Ref>)";
}
Console.WriteLine(lris.Refs[0].startString);
ListRefNoSetter lrns = new ListRefNoSetter(){ Refs = new List<Ref> { new Ref() } };
foreach(Ref r in lrns.Refs)
{
//ModifyRef(r);
r.startString="modified ListRefNoSetter()'s Refs (a List<Ref>)";
}
Console.WriteLine(lrns.Refs[0].startString);
}
public void ModifyRef(Ref r)
{
r.startString="modified";
}
public class ListRefImplicitSetter
{
public List<Ref> Refs { get { return new List<Ref> { new Ref() }; } }
}
public class ListRefNoSetter
{
public List<Ref> Refs { get; set;}
}
public class ListRef
{
public List<Ref> Refs {
get { return _Refs; }
set { _Refs = value; }
}
private List<Ref> _Refs;
}
public class Ref
{
public int startInt;
public string startString;
public Ref()
{
startInt=1;
startString="start - this has not been modified";
}
}
// Define other methods and classes here
/*BEFORE:
NOTE: _ExpirableItems is always null; and Data didn't change, so it always returned Data!
public List<T> ExpirableItems
{
get { return _ExpirableItems ?? Data.Deserialize<List<T>>() ?? new List<T>(); }
set { _ExpirableItems = value; }
}
private List<T> _ExpirableItems;
AFTER:
public List<T> ExpirableItems
{
get {
if(null==_ExpirableItems){
_ExpirableItems = Data.Deserialize<List<T>>() ?? new List<T>();
}
return _ExpirableItems;
}
set { _ExpirableItems = value; }
}
private List<T> _ExpirableItems;
*/
/* BEFORE:
IEnumerable<T> removedItems = ExpirableItems.Where(i => i.IsExpired);
//This actually removes them;
int num = ExpirableItems.RemoveAll(i => i.IsExpired);
return removedItems;
Note that ExpirableItems.Where is deferred;
But RemoveAll() is not deferred, and modifies the item in place;
I wanted to do both; remove the items and get the items that were removed;
Probably better to do an approach like this: http://stackoverflow.com/questions/419019/split-list-into-sublists-with-linq
A nice test would be Trace.AssertIs
AFTER:
IEnumerable<T> removedItems = ExpirableItems.Where(i => i.IsExpired).ToList();
//This actually removes them;
int num = ExpirableItems.RemoveAll(i => i.IsExpired);
return removedItems;
Or I could force execution with ToList();
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment