C # reference to loop variable

Is it possible in C # something like the following

foreach (ref string var in arr) { var = "new value"; } 

so that var is treated as a reference, and assigning to var would change the element of the array?

+7
reference c #
source share
5 answers

There is no such design for updating the cycle; the iterator is read-only. For example, the following provides a perfectly valid iterator:

 public IEnumerable<int> Get1Thru5() { yield return 1; yield return 2; yield return 3; yield return 4; yield return 5; } 

How will it be updated? What will update?

If the data is an array / list / etc, then something like:

 for(int i = 0 ; i < arr.Length ; i++) { arr[i] = "new value"; } 

Or other parameters depending on the specific container.


Update; when click , extension method:

 public static void UpdateAll<T>(this IList<T> list, Func<T, T> operation) { for (int i = 0; i < list.Count; i++) { list[i] = operation(list[i]); } } static void Main() { string[] arr = { "abc", "def", "ghi" }; arr.UpdateAll(s => "new value"); foreach (string s in arr) Console.WriteLine(s); } 
+22
source share

Not. The foreach is just syntactic sugar on top of IEnumerable . This interface defines a method to get en IEnumerator , which in turn has read-only enumeration methods:

  • Current: object
  • MoveNext (): bool
  • Reset (): void
+2
source share
 foreach(string s in strings) { Console.WriteLine(s); } 

- shortcut for the compiler for:

 IEnumerator e = strings.GetEnumerator(); string s; while(e.MoveNext()) { s = e.Current; Console.WriteLine(s); } 

Since IEnumerator.Current is a get-only property, you cannot set a value.

 // Non-generic IEnumerator shown. interface IEnumerator { bool MoveNext(); object Current { get; } void Reset(); } 

If you want to support an updatable enumerator, you will need to create it yourself, but you cannot use "foreach" with it, and you will have to implement wrappers around all the usual IEnumerable classes.

You need to analyze the current situation and figure out how to update. If you use the IList interface, you can:

 for(int i = 0; i < strings.Count; ++i) { string s = strings[i]; //do work s = s.ToUpperInvariant(); strings[i] = s; } 
+2
source share

In case of a line is not; C # strings are immutable (cannot be changed). If you have listed objects of a different, mutable type, you can change the properties of these objects.

Just to illustrate what Jacob is talking about. Consider the code snippet below:

 class MyInt { public int Val { get; set; } public MyInt(int val) { this.Val = val; } } class Program { static void Main(string[] args) { MyInt[] array = new MyInt[] { new MyInt(1), new MyInt(2) }; foreach (var obj in array) Console.Write("{0}\t", obj.Val); foreach (var obj in array) { obj = new MyInt(100); // This doesn't compile! the reference is read only obj.Val *= 10; // This works just fine! } foreach (var obj in array) Console.Write("{0}\t", obj.Val); } } 

In fact, if you try to assign "obj" as described above, you will get a compile-time error. But nothing prevents you from changing the properties of MyInt using the "obj" link

+1
source share

In case of a line is not; C # lines are immutable (cannot be changed). If you have listed objects of a different, mutable type, you can change the properties of these objects.

0
source share

All Articles