我有一个对象集合,想修改该集合中某个对象的属性。如果我只有一个对象,我的 ChangeStuff 方法可以正常工作,并且在从该方法返回时修改对象。 (主要的前 4 行)
但是,当遍历集合时,我想我遗漏了一些东西,因为我更改的值似乎停留在 foreach 循环的范围内。
我不应该传递对象 by ref (或使用 out 参数),因为我没有返回新值。
对于大代码块,我深表歉意,但它已尽可能简化,并且仍然可以证明我的问题。
class foobar
{
public string string1;
public string string2;
}
static void Main(string[] args)
{
/***** THIS WORKS!! *****/
foobar singleFb = new foobar { string1 = "foo2", string2 = "bar2" };
ChangeStuff(singleFb);
Console.WriteLine(singleFb.string1 + ", " + singleFb.string2);
Console.ReadLine(); //pause to read output
/***** THIS DOESN'T WORK!! *****/
List<foobar> myList = new List<foobar> { new foobar {string1 = "foo1", string2 = "bar1"}, new foobar {string1 = "foo2", string2 = "bar2"}, new foobar {string1 = "something else", string2 = "something else again"} };
IEnumerable<foobar> fbs = myList.Where(x => x.string1.StartsWith("foo"));
ChangeStuff(fbs);
foreach (foobar fb in fbs)
{
Console.WriteLine(fb.string1 + ", " + fb.string2);
}
Console.ReadLine(); //pause to read output
}
static void ChangeStuff(IEnumerable<foobar> fbs)
{
foreach (foobar fb in fbs)
{
ChangeStuff(fb);
}
}
static void ChangeStuff(foobar fb)
{
if (fb.string1.Contains("2"))
fb.string1 = "changed!";
}
}
我需要更改什么才能修改集合中的对象?
编辑:另外,刚刚注意到当我的收藏集回来时实际上完全没有“foo2”......很奇怪。我实际上在我的应用程序中使用 IQueryable,并没有遇到这个问题。 IE。我拥有所有对象,只是没有正确修改它们。不确定这里发生了什么......
编辑 2: 感谢您的回答,现在非常有道理。如果我按如下方式更改我的
ChangeStuff 方法,它会按我预期的那样工作:
static void ChangeStuff(foobar fb)
{
if (fb.string2.Contains("2"))
fb.string2 = "changed!";
}
请您参考如下方法:
您看到的结果是由于 IEnumerable<T> 的延迟加载性质造成的.第二次枚举“fbs”时,属性“string1”已更改,因此它不再匹配 Where谓词。
如果您枚举 IEnumerable立即并将结果存储在具体列表中(例如,通过使用 ToList() 或 ToArray() ,然后第二个枚举将显示您期望的结果:
IEnumerable<foobar> fbs = myList.Where(x => x.string1.StartsWith("foo")).ToList();
这是原始版本代码中发生的事情:
List<foobar> myList = new List<foobar> { new foobar { string1 = "foo1", string2 = "bar1" }, new foobar { string1 = "foo2", string2 = "bar2" }, new foobar { string1 = "something else", string2 = "something else again" } };
IEnumerable<foobar> fbs = myList.Where(x => x.string1.StartsWith("foo"));
// here the enumeration yields objects #1 and #2
// object #2 has its "string1" property modified to "changed!"
ChangeStuff(fbs);
// here the enumeration is re-evaluated, and now object #2 no longer matches the predicate
// only object #1 ("foo1") is output
foreach (foobar s in fbs)
{
Console.WriteLine(s.string1);
}
