Reputation:
I used the following code to step through an IEnumerable.
IEnumerable<Thing> things = ...;
foreach (Thing thing in things)
thing = method(thing);
The compiler disagrees with it since I'm referring to thing that is the iterating variable. Of course, I intend to affect the underlying object in my list, instead. How do I do that?
For now, I went with the work-around using a numerated iteration but there are two issues there. For one, it's not good coding IMHO. Besides that, it requires me to change my things from IEnumerable to IList (or should I even be using List?!), which will bite be in my lower back when things get big.
//List<Thing> things = ...;
IList<Thing> things = ...;
for (int i = 0; i < things.Count(); i++)
things[i] = method(things[i]);
Upvotes: 1
Views: 215
Reputation: 18096
Item replacement can be easy done using some collection, for example, array or List<T>
(as you described) by using for
loop (not foreach
).
There is no way to replace the object using foreach
statement.
If you really want to use IEnumerable<T>
interface there are two alternatives:
Transform the sequence of Thing
s (see IEnumerable<T>.Select()
method). The source sequence and source instances of Thing
are not modified in this case.
For example:
var newThings = things.Select(t => new Thing(/* pass different values using original t instance */));
Update the state of each instance:
class Thing
{
public void UpdateState(/* parameters */)
{
// Update field/property values, etc.
}
}
...
foreach (var thing in things)
thing.UpdateState(/* new values */);
Upvotes: 1
Reputation: 6434
If the length of the IEnumerable
will reamin the same, I would use ToArray()
and iterate with a for
loop.
For example:
char[] chars = "somestring".ToArray();
for (int i = 0; i < chars.Length; i++)
{
chars[i] = SomeMethod();
}
For modifying something in the collection.
Thing[] things = ...;
for (int i = 0; i < things .Length; i++)
{
AddOne(ref things[i]);
}
public void AddOne(ref Thing t)
{
t.Foo += 1;
}
Upvotes: 0
Reputation: 713
you cant change the references when iterating items inside list since its restricted in enumerators but you can change objects inside items....
use powerful LINQs or just clone your list like ToList() or ToArray().
Upvotes: 1
Reputation: 9002
If you are going to run the method on all elements, why don't you transform the whole collection:
public IEnumerable<Thing> TransformThings(IEnumerable<Thing> input)
{
foreach (var thing in input)
yield return method(thing);
}
You can use it like this:
var transformedThings = TransformThings(things);
This will transform each element as you iterate over the collection, meaning you don't have to enumerate the whole collection to memory.
EDIT
Even SIMPLER:
var transformedThings = things.Select(thing => method(thing));
Upvotes: 2
Reputation: 236208
You can project sequence with Linq:
var transformedThings = things.Select(t => method(t));
Upvotes: 4