Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 修改集合中对象的属性_C#_Linq_Ref - Fatal编程技术网

C# 修改集合中对象的属性

C# 修改集合中对象的属性,c#,linq,ref,C#,Linq,Ref,我有一个对象集合,希望修改该集合中对象的属性。如果我只有一个对象,我的ChangeStuff方法工作得很好,当从该方法返回时,对象会被修改。主管道的前4条管线 然而,当遍历集合时,我想我遗漏了一些东西,因为我更改的值似乎卡在了foreach循环的范围内 我不必传递对象或使用out参数,因为我不会返回新值 很抱歉,代码块太大了,但它已经尽我所能简化了,并且仍然演示了我的问题 class foobar { public string string1;

我有一个对象集合,希望修改该集合中对象的属性。如果我只有一个对象,我的ChangeStuff方法工作得很好,当从该方法返回时,对象会被修改。主管道的前4条管线

然而,当遍历集合时,我想我遗漏了一些东西,因为我更改的值似乎卡在了foreach循环的范围内

我不必传递对象或使用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!";
    }
}

处理LINQ时要记住的最重要的一点是,这些方法不会返回查询结果,而是返回一个表示查询本身的对象。在枚举序列时,执行查询并返回项

fbs是一个查询,用于获取第一个字符串以foo开头的所有项目。它不是前两个项的集合,即使这些是在第一次定义查询时执行该查询时将返回的项


第一次执行查询并迭代结果时,返回两个项目并尝试同时更改它们,只有一个项目实际被ChangeStuff更改。然后再次执行查询以打印结果,但现在更改的项不符合查询的条件,因此不会返回。只返回未更改的第一项。如果迭代列表,而不是查询,您将看到更改的项。

处理LINQ时要记住的最重要的一点是,这些方法不会返回查询结果,而是返回一个表示查询本身的对象。在枚举序列时,执行查询并返回项

fbs是一个查询,用于获取第一个字符串以foo开头的所有项目。它不是前两个项的集合,即使这些是在第一次定义查询时执行该查询时将返回的项


第一次执行查询并迭代结果时,返回两个项目并尝试同时更改它们,只有一个项目实际被ChangeStuff更改。然后再次执行查询以打印结果,但现在更改的项不符合查询的条件,因此不会返回。只返回未更改的第一项。如果您迭代列表,而不是查询,您将看到更改的项。

您看到的结果是由于IEnumerable的延迟加载特性。第二次通过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);
}

您看到的结果是由于IEnumerable的延迟加载特性。第二次通过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);
}

foobar是一个结构吗?请发布一个简洁但完整的代码示例,以可靠地演示该问题。@PeterDuniho,对不起,我没有复制该类。请参见编辑。foobar是结构吗?请发布一个简洁但完整的代码示例,以可靠地演示该问题。@PeterDuniho,对不起,我没有复制该类。请参见编辑。啊。。。这是有道理的。听起来我的最佳选择是在编辑收藏之前转换.ToList?@sǝɯɐſ这会起作用,但在这种情况下,打印结果可能只是打印整个列表。在我看来,这是正确的测试。不管怎样,关键是你没有正确地观察到确实正在进行的更改。谢谢你给出了一个很好的答案,我喜欢斜体字,但我必须给@McGarnagle打分,因为他的代码示例让我更清楚了。啊。。。这是有道理的。听起来我的最佳选择是在编辑收藏之前转换.ToList?@sǝɯɐſ这会起作用,但在这种情况下,打印结果可能只是打印整个列表。在我看来,这是正确的测试。不管怎样,关键是你没有正确地观察到确实正在进行的更改。谢谢你的回答,我喜欢斜体字,但我必须给@McGarnagle打分,因为他的代码示例让我更清楚了。谢谢!完全有道理,见编辑2。我假设这与IQueryable的工作方式相同-当prin
如果删除属性,它将从数据库重新加载,我以前的编辑将丢失?我不确定您的更改是否会被删除,也就是说,我认为数据上下文可能仍然保留您的更改,并且在您调用SubmitChanges?时,这些更改将提交到数据库?。但是是的,IQueryable与IEnumerable类似,因为它每次都会转到源代码,除非您首先在具体列表中意识到它。谢谢!完全有道理,见编辑2。我假设这与IQueryable的工作方式相同-当打印属性时,它将从数据库重新加载,并且我以前的编辑将丢失?我不确定您的更改是否会被删除,也就是说,我认为数据上下文可能仍然保留您的更改,并且在您调用SubmitChanges?时,这些更改将提交到数据库?。但是是的,IQueryable与IEnumerable类似,因为它每次都会转到源代码,除非您首先在具体列表中意识到它。