【问题标题】:IEnumerable<T> does not reflect changes on elements [duplicate]IEnumerable<T> 不反映元素的变化[重复]
【发布时间】:2018-02-26 23:34:10
【问题描述】:

我在使用 IEnumerable 时遇到问题。 _entities 是来自 EF Core DbContext 的 IQueryable。 _result 是 IEnumerable。

此代码不起作用; _result 仍未排序。

var _result = _entities.Select(s => this.IMapper.Map<Models.role, DTO.role>(s));

foreach (var _role in _result)
{
    _role.permissions = _role.permissions.OrderBy(o => o.module).ThenBy(o => o.feature).ToArray();
}

return _result;

此代码确实有效; _result 已排序。

var _result = _entities.Select(s => this.IMapper.Map<Models.role, DTO.role>(s)).ToArray();

foreach (var _role in _result)
{
    _role.permissions = _role.permissions.OrderBy(o => o.module).ThenBy(o => o.feature).ToArray();
}

return _result;

谁能解释一下?

【问题讨论】:

  • 您说 _result 仍未排序,但您没有任何代码对 _result 进行排序。您正在对 _result 列表中的另一个列表进行排序,这是您的意思吗?
  • @贾斯汀:确实。我的糟糕,不清楚的帖子。 _result 的属性permission 仍未排序。
  • IEnumerable 是一个基础接口,但最好将IEnumerables 视为集合的投影,而不是集合本身。如果您想以某种方式改变集合或其项目,请考虑首先将投影转换为集合类型(列表等)
  • 旁白:您最好将此代码放入 Mapper 本身,以便每个到 DTO.role 的映射都带有排序权限。这也将解决您的 Enumerable 被评估两次(或更多)的问题。

标签: c# .net-core ienumerable


【解决方案1】:

原因是 LINQ 在 IEnumerable 的迭代和 IEnumerable 的每次迭代上评估 Select

这意味着如果您对从Select 返回的项目进行更改,这些对象将被丢弃,并且在下一次迭代中,您将用原始数据押注一个新对象。

输入ToArray 将导致Select 的结果存储在集合中,因此您对对象执行的更改将按预期工作。

为了演示这种行为,您可以在添加一些 Console.WriteLine 时看到输出:

class Item
{
    public int Value { get; set; }
    static int id = 0;
    public int Id { get; } = id++; // generate next id every time
}
static void Main(string[] args)
{
    var range = new int[] { 1, 2, 3 }
        .Select(i => new Item { Value = i });

    foreach (var item in range)
    {
        Console.WriteLine(item.Value + "- id:" + item.Id);
        // Will output 
        //1- id:0
        //2- id:1
        //3- id:2
    }
    foreach (var item in range)
    {
        Console.WriteLine(item.Value + "- id:" + item.Id);
        // Will output 
        //1- id:3
        //2- id:4
        //3- id:5
    }
}

【讨论】:

  • 所以它是 IEnumerable AND Select 的组合还是 IEnumerable 的默认行为?
  • @Luke1988 IEnumerable 只是描述了如何迭代,迭代中的项目如何构建取决于 IEnumerable 的实现。 Select 是惰性的,会在需要时创建对象,并且不会在内存中保留任何对象。如果您遍历列表,则行为会有所不同,因为该迭代每次都返回相同的对象
猜你喜欢
  • 2021-12-23
  • 1970-01-01
  • 1970-01-01
  • 2013-08-22
  • 2012-02-10
  • 1970-01-01
  • 2012-09-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多