如何在foreach中引用实际元素
本文关键字:元素 引用 foreach | 更新日期: 2023-09-27 18:04:22
我使用了下面的代码来遍历一个IEnumerable。
IEnumerable<Thing> things = ...;
foreach (Thing thing in things)
thing = method(thing);
编译器不同意,因为我引用了东西,这是迭代变量。当然,我打算影响列表中的底层对象。我怎么做呢?
现在,我使用了一个数值迭代的解决方案,但是有两个问题。首先,我认为这不是一个好的编码。除此之外,它要求我将things从IEnumerable更改为IList(或者我甚至应该使用List?!),当things变大时,将放在我的下背。
//List<Thing> things = ...;
IList<Thing> things = ...;
for (int i = 0; i < things.Count(); i++)
things[i] = method(things[i]);
您可以使用Linq:
投影序列 var transformedThings = things.Select(t => method(t));
如果要在所有元素上运行该方法,为什么不转换整个集合:
public IEnumerable<Thing> TransformThings(IEnumerable<Thing> input)
{
foreach (var thing in input)
yield return method(thing);
}
你可以这样使用:
var transformedThings = TransformThings(things);
这将在您遍历集合时转换每个元素,这意味着您不必将整个集合枚举到内存中。
编辑
更简单:
var transformedThings = things.Select(thing => method(thing));
你不能改变引用时迭代列表中的项目,因为它在枚举器的限制,但你可以改变项目中的对象....
使用强大的linq或只是克隆你的列表,如ToList()或ToArray()。
项目替换可以很容易地完成使用一些集合,例如,数组或List<T>
(如您所描述的)通过使用for
循环(不是foreach
)。
无法用foreach
语句替换对象
如果你真的想使用IEnumerable<T>
接口,有两个选择:
-
变换
例如:Thing
s序列(参见IEnumerable<T>.Select()
方法)。在本例中,Thing
的源序列和源实例没有被修改。var newThings = things.Select(t => new Thing(/* pass different values using original t instance */));
-
更新每个实例的状态:
class Thing { public void UpdateState(/* parameters */) { // Update field/property values, etc. } } ... foreach (var thing in things) thing.UpdateState(/* new values */);
如果IEnumerable
的长度保持不变,我将使用ToArray()
并迭代for
循环。
char[] chars = "somestring".ToArray();
for (int i = 0; i < chars.Length; i++)
{
chars[i] = SomeMethod();
}
用于修改集合中的内容。
Thing[] things = ...;
for (int i = 0; i < things .Length; i++)
{
AddOne(ref things[i]);
}
public void AddOne(ref Thing t)
{
t.Foo += 1;
}