Skip to main content
 首页 » 编程设计

c#之修改集合中对象的属性

2024年01月13日28pengyingh

我有一个对象集合,想修改该集合中某个对象的属性。如果我只有一个对象,我的 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); 
}