views:

1228

answers:

8

Consider this:

List<MyClass> obj_list = get_the_list();
foreach( MyClass obj in obj_list )
{
    obj.property = 42;
}

Is 'obj' a reference to the corresponding object within the list so that when I change the property the change will persist in the object instance once constructed somewhere?

+10  A: 

Yes, obj is a reference to the current object in the collection (assuming MyClass is in fact a class). If you change any properties via the reference, you're changing the object, just like you would expect.

Be aware however, that you cannot change the variable obj itself as it is the iteration variable. You'll get a compile error if you try. That means that you can't null it and if you're iterating value types, you can't modify any members as that would be changing the value.

The C# language specification states (8.8.4)

"The iteration variable corresponds to a read-only local variable with a scope that extends over the embedded statement."

Brian Rasmussen
This is true even for value types, i.e. structs.
technophile
@technophile: Actually you can't modify obj if MyClass is a struct, cause you're not allowed to modify the iteration variable itself.
Brian Rasmussen
@Brian Rasmussen: Why cant we modify the enumerable object ?
Amit
@Amy: According to the language specification (8.8.4) "The iteration variable corresponds to a read-only local variable with a scope that extends over the embedded statement."
Brian Rasmussen
public class MyClass { public int val; } class MyApp { public static void Main(String[] args) { IList<MyClass> list = new List<MyClass>(); MyClass obj1 = new MyClass(); obj1.val = 10; list.Add(obj1); MyClass obj2 = new MyClass(); obj2.val = 10; list.Add(obj2); foreach (MyClass obj in list) { obj.val = 20; } } }refer this code. This works ;)
Amit
@Amy: yes it does but you are not modifying obj itself, you're modifying what it points to. There's a difference. Try to set obj to null and you'll get the compile error.
Brian Rasmussen
Yes, you are right. It's giving compilation error.But it's quite strange.
Amit
@Amy: Not really. A value type variable stores the actual value. A reference type variable stores a reference to an object. It is the variable and not the referenced object that is read only and thus you can change the object via the reference, but you cannot change the reference itself.
Brian Rasmussen
+1  A: 

Short answer: Yes.

Kirschstein
A: 

Well, without understanding exactly what you mean by "Iterate by reference", I can't answer specifically yes or no, but I can say that what's going on under the surface is that the .net framework is constructing an "enumerator" class for each time client code calls a foreach, for the life of the foreach, that maintains a reference pointer into the collection being iterated over, and each time your foreach iterates, ir "delivers" one item and "increments" the pointer or reference in the enumerator to the next item...

This happens regardless of whether the items in the collection you are iterating over are values types or reference types.

Charles Bretana
A: 

obj is a reference to an item inside the List, hence if you change it's value it will persist. Now what you should be concerned about is whether or not get_the_list(); is making a deep copy of the List or returning the same instance.

Stan R.
It won't make a difference to the functionality he's interested in. Four copies of the same list will all reference the same actual objects, so whether you modify them from List1 or List3, either will result in the original object being modified. The only thing it will affect is if you add or remove items to/from the list, that wouldn't affect any copies of the list.
technophile
yes, the short answer of course is "yes, its a ref type", but the problems he might run into is if he it creates a copy of some original list, so if he calls get_the_list(); changes it and then calls get_the_list(); again somewhere else in the code, he might not get the results he expected.
Stan R.
btw technophile I am talking about a deep copy..
Stan R.
+6  A: 

You've asked 2 different questions here, lets take them in order.

Does a foreach loop iterate by reference?

If you mean in the same sense as a C++ for loop by reference, then no. C# does not have local variable references in the same sense as C++ and hence doesn't support this type of iteration.

Will the change be persisted

Assuming that MyClass is a reference type, the answer is yes. A class is a reference type in .Net and hence the iteration variable is a reference to the one variable, not a copy. This would not be true for a value type.

JaredPar
A: 

Yes, that's also why you cannot alter the enumerable object in the context of the foreach statement.

Brian Scott
A: 

Answer is Yes.

Even i 'm thinking on why cant we change the enumerable object ???

@Brian Rasmussen: I think we can, Please suggest ???

Amit
A: 

this is true as long as it is not a struct.

Deepfreezed