sha*_*kin 64 c# foreach reference
考虑一下:
List<MyClass> obj_list = get_the_list();
foreach( MyClass obj in obj_list )
{
obj.property = 42;
}
Run Code Online (Sandbox Code Playgroud)
'obj'是对列表中相应对象的引用,这样当我更改属性时,更改将在构造到某处的对象实例中持续存在吗?
Bri*_*sen 63
是的,obj是对集合中当前对象的引用(假设MyClass实际上是一个类).如果您通过引用更改任何属性,那么您正在更改对象,就像您期望的那样.
但请注意,您无法更改变量obj本身,因为它是迭代变量.如果你尝试,你会得到一个编译错误.这意味着您不能将其置零,如果您正在迭代值类型,则无法修改任何成员,因为这会更改值.
C#语言规范声明(8.8.4)
"迭代变量对应于只读局部变量,其范围扩展到嵌入语句."
jac*_*cso 21
是的,直到您将通用类型从List更改为IEnumerable ..
Jar*_*Par 19
你在这里问过两个不同的问题,让我们按顺序排列.
如果你的意思与C++ for while循环相同,那么没有.C#没有与C++相同的局部变量引用,因此不支持这种类型的迭代.
假设MyClass是一个引用类型,答案是肯定的.类是.Net中的引用类型,因此迭代变量是对一个变量的引用,而不是副本.对于值类型,情况并非如此.
mrz*_*epa 15
好吧,当我迭代var collection时,我的更改在foreach循环中没有更新:
var players = this.GetAllPlayers();
foreach (Player player in players)
{
player.Position = 1;
}
Run Code Online (Sandbox Code Playgroud)
当我将var更改为List时,它开始工作.
小智 7
你可以在这个例子中(使用a List<T>),但如果你要迭代泛型,IEnumerable<T>那么它就会依赖于它的实现.
如果它仍然是一个List<T>或者T[]例如,所有都将按预期工作.当你IEnumerable<T>使用yield构建的时候,就会遇到大问题.在这种情况下,您不能再修改T迭代中的属性,并且如果IEnumerable<T>再次迭代它们,则期望它们存在.
也许你觉得在 C# 7.3 版本中可以通过引用更改值,前提是枚举器的Current属性返回引用类型。以下内容是有效的(来自 MS 文档的逐字副本):
Span<int> storage = stackalloc int[10];
int num = 0;
foreach (ref int item in storage)
{
item = num++;
}
Run Code Online (Sandbox Code Playgroud)
在C# foreach 语句中阅读有关此新功能的更多信息 | 微软文档。