在foreach循环中修改对象的属性无法生效?

5

这让我感到困惑。我正在使用PetaPoco从数据库检索一些值,然后循环遍历它们并检索一个值以分配给每个对象的一个属性。

    public IEnumerable<RetreaveIndex> FillResults(IEnumerable<RetreaveIndex> results)
    {
        //add the associated users
        foreach (RetreaveIndex index in results)
        {
            index.AssociatedUsers = _registeredUserDao.GetUsersByIndex(index).ToList();
        }
        return results;
    }

当我在foreach循环期间设置断点时,AssociatedUsers属性被正确设置。 during foreach loop 但是,在循环结束时的断点中,它没有保存? enter image description here 我很困惑,Index不应该是一个正在被修改的内存位置的引用吗?毕竟它是一个对象。我在这里错过了什么?
4个回答

8
  1. 什么是IEnumerable实现?它能够返回对象的副本吗?

  2. RetreaveIndex是一个结构体,因此是值类型吗?如果是这样,那么变量index将会是一个副本。


这是一个对象(请参见原问题底部)。我查看了PetaPoco源代码,发现我调用的方法Query<T>()使用Yield Return返回IENumerable。当我将调用更改为返回List的Fetch<T>()时,它起作用了。也许我需要更多地了解yield return,我以为它只是一种语法糖来构造某种列表,我猜错了吗? - RodH257
1
yield return会导致方法体被拆分成一个巨大的case语句,成为一个新IEnumerator类的MoveNext方法的主体。 - Dark Falcon
我已经使用IEnumerables工作多年了,令人惊讶的是这是我第一次遇到这个问题...(这完全让我困惑)干杯! - FBryant87

4

根据IEnumerable的实现方式,它不要求在下一次枚举数据时返回与之前相同的对象。在foreach循环之前将IEnumerable转换为List,然后返回它。


1

来自项目网站

查询 vs 获取

Database类有两种检索记录的方法:Query和Fetch。这两种方法几乎完全相同,除了Fetch返回一个POCO列表,而Query使用yield return迭代结果,而不将整个集合加载到内存中。

换句话说,Query每次重新从后备存储加载值,并且在枚举后不保留项目。当您在循环结束后再次查看项目时,该项目将从后备存储重新加载。


0
实际上,你误解了yield return语法的输出。发生的情况是,在迭代yield return返回的IEnumerable时,紧随其后的代码也被执行。从技术角度来说,yield return是进行惰性评估。因此,在你的foreach循环中,它会调用代码来生成IEnumerable中的每个项目。
CodeProject上的以下帖子非常好地解释了这种行为: http://www.codeproject.com/Articles/38097/The-Mystery-Behind-Yield-Return.aspx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接