[英]Assign value to iteration variable in C#?
我在C#中使用foreach
有以下代码。 我在一个循环中修改了List<T>
,在另一个循环中修改了一个string
数组。
我们不能直接为迭代变量赋值或null,但是我们可以修改它的属性,并且修改最终反映在List
。
所以这基本上意味着迭代变量是对列表中元素的引用,那么为什么我们不能直接为它赋值?
class Program
{
public static void Main(string[] args)
{
List<Student> lstStudents = Student.GetStudents();
foreach (Student st in lstStudents)
{
// st is modified and the modification shows in the lstStudents
st.RollNo = st.RollNo + 1;
// not allowed
st = null;
}
string[] names = new string[] { "me", "you", "us" };
foreach (string str in names)
{
// modifying str is not allowed
str = str + "abc";
}
}
}
学生班:
class Student
{
public int RollNo { get; set; }
public string Name { get; set; }
public static List<Student> GetStudents()
{
List<Student> lstStudents = new List<Student>();
lstStudents.Add(new Student() { RollNo = 1, Name = "Me" });
lstStudents.Add(new Student() { RollNo = 2, Name = "You" });
lstStudents.Add(new Student() { RollNo = 3, Name = "Us" });
return lstStudents;
}
}
foreach
的迭代变量不是 “对列表中元素的引用” - 它只是通过GetEnumerator()
获得的迭代器实现中来自.Current {get;}
的值 - 最常见的是通过IEnumerator[<T>]
但并非总是如此 - 实际上对于List<T>
它是List<T>.Enumerator
值。 在一般情况下,分配给迭代器变量没有“意义”。 考虑:
IEnumerable<int> RandomSequence(int count) {
var rand = new Random();
while(count-->0) yield return rand.Next();
}
这将与 foreach
完全相同 - 分配给它的意义是什么?
因此, foreach
没有提供分配给迭代器变量的工具。
它是一种引用类型,当然,如果它们是可写的,您可以修改它的属性,并且这些更改将反映在引用所引用的对象中。
根据定义,引用类型的变量是对对象的引用。 但这与对实际存储位置(例如变量或列表条目)的引用不同。
您可以想象它像Student
变量只包含查找原始对象的地址。 通过将列表条目复制到变量,您只需复制地址,因此现在您有两个地址,一个在列表中,一个在变量中。 通过重新分配变量,您将在其中写入另一个地址,但这不会影响列表中的原始条目。 它也不会覆盖前面提到的变量的对象。
话虽这么说, foreach
可能不允许你重新分配迭代变量,因为它可能导致混乱/错误。 当前实现的方式,你总是知道迭代变量是当前元素。
这是因为编译器使用Enumerator
实现foreach
。 枚举器只能在封闭的集合中前进移动,它们不能改变它们迭代的集合。
这是一个应该说清楚的具体例子。
想象一下,你实现了IEnumerable<int>
如下所示:
public static IEnumerable<int> OneToTen()
{
for (int i = 1; i <= 10; ++i)
{
yield return i;
}
}
鉴于此,如果在以下循环中您可以分配给n
,这意味着什么?
foreach (var n in OneToTen())
{
n = 1; // Change original "collection"? There isn't one!
}
编译器可以让你更改n
而不需要改变迭代的东西,但这会产生误导 - 这就是编译器不允许它的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.