C#引用循环变量

时间:2009-07-03 07:05:07

标签: c# reference

C#中是否可能出现以下内容

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

这样var变量被视为参考,分配给var会改变数组元素吗?

5 个答案:

答案 0 :(得分:22)

更新循环没有这样的构造;迭代器是只读的。例如,以下提供了一个完全有效的迭代器:

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

如何更新? 会更新什么

如果数据是数组/列表/等,那么类似于:

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

或其他选项,具体取决于具体的容器。


更新;在推送,一种扩展方法:

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);
}

答案 1 :(得分:2)

没有。 foreach语句只是IEnumerable接口上的语法糖。此接口定义了一个获取en IEnumerator的方法,该方法又具有执行只读枚举的方法:

  • 当前:对象
  • MoveNext():bool
  • 重置():无效

答案 2 :(得分:2)

foreach(string s in strings)
{
  Console.WriteLine(s);
}

是:

的编译器快捷方式
IEnumerator e = strings.GetEnumerator();
string s;
while(e.MoveNext())
{
  s = e.Current;
  Console.WriteLine(s);
}

由于IEnumerator.Current是get-only属性,因此无法设置该值。

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

如果你想支持一个可更新的枚举器,你需要自己创建它 - 但是你将无法使用它“foreach”,并且你必须在所有常见的IEnumerable类周围实现包装器。

您必须分析当前情况并找出如何更新。如果您正在使用IList接口,则可以执行以下操作:

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

答案 3 :(得分:1)

  

如果是字符串,则不; C#   字符串是不可变的(不能   改变)。如果你在列举   不同的,可变类型的对象,   你可以改变那些的属性   对象。

只是为了说明雅各在谈论什么。请考虑以下代码段:

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);
    }
}

实际上,如果您尝试按上述方式分配“obj”,则会出现编译时错误。但没有什么能阻止你通过“obj”引用来修改MyInt的属性

答案 4 :(得分:0)

如果是字符串,则不; C#字符串是不可变的(不能更改)。如果要枚举不同的可变类型的对象,则可以更改这些对象的属性。