18.9.3迭代变量

回顾一下,foreach语句和for语句的区别之一就是,foreach使用了迭代变量。迭代变量是只读的,代码清单18-13将不能通过编译。

代码清单18-13 迭代变量是只读的


1 namespace ProgrammingCSharp4

2{

3 class Person

4{

5 public int Age{get;set;

6

7 public override string ToString()

8{

9 return string.Format(“年龄:{0}”,Age);

10}

11}

12

13 class ArraySample

14{

15 public static void Main()

16{

17 Person[]array1={new Person{Age=10},new Person{Age=20},new Person{Age=30}};

18

19 foreach(Person person in array1)

20{

21 person=new Person{Age=40};//错误

22 System.Console.WriteLine(person);

23}

24}

25}

26}


在上述代码中,试图给迭代变量person赋值,编译器将抛出如下异常:

"person"是一个“foreach迭代变量”,无法为它赋值

接下来,我们对出错的第21行稍加改造,如代码清单18-14所示。

代码清单18-14 通过迭代变量改变对象的值


foreach(Person person in array1)

{

person.Age=50;

System.Console.WriteLine(person);

}


程序正常运行了。运行结果如下:


年龄:50

年龄:50

年龄:50


接下来,我们分析一下为什么代码清单18-13编译出错,而代码清单18-14却能正常编译。因为person变量在这里是一个引用类型的变量,那么在代码清单18-13中向person变量赋值,就是传递引用,就是改变person变量的指向,由原来作为“数据1”的引用改成作为“数据2”的引用,这是不允许的,因为person变量只读;而在代码清单18-14中,是通过引用来改变数据的值,并没有改变引用本身,因此是合法的,其原理如图18-19所示。

18.9.3迭代变量 - 图1

图 18-19 对于两段代码的原理分析

总结一下,之所以可以通过迭代变量改变数据的值,是因为数组中的数据元素是引用类型,因此迭代变量是引用类型,引用类型的引用和数据分别位于栈和堆,这时的迭代变量实际上是位于栈中的一个引用,只要引用不改变,就可以通过引用改变数据。而对于值类型,值类型的值和变量名都位于栈中,我们无法改变值类型数组的数据。