【问题标题】:Modifiying IEnuemerable in for loops在 for 循环中修改 IEnumerable
【发布时间】:2017-04-04 00:20:00
【问题描述】:

如何修改 IEnuemerable<ProductLineDto> 内的嵌套元素

所以基本上循环看起来像这样 product lines > project types > projects > sub projects > 其中包含更多 sub projectsactivities

问题是我无法修改 subprojectactivities,这应该在递归函数 GetActivitiesForActivityPerson 中发生

        private IEnumerable<ProductLineDto> GetGanttDataByPerson(IEnumerable<ProductLineDto> ganttData, GanttFilterDto ganttFilterDataModel)
        {
            if(ganttFilterDataModel.PersonId == null)
                return ganttData;

            var gdata = ganttData.CopyProductLineDtosEnumerable().ToList();

            for(var i = 0; i < gdata.Count; i++)
            {
                    var pType = gdata[i].ProjectType.CopyProjectTypeDtoEnumerable().ToList();

                    for (var j = 0; j < pType.Count; j++)
                    {
                        var projects = pType[j].Projects.CopyProjectDtosEnumerable().ToList();
                        for (var a = 0; a < projects.Count; a++)
                        {
                            // projects[a].Children is not being modified
                            projects[a].Children = GetActivitiesForActivityPerson(projects[a].Children, ganttFilterDataModel.PersonId);
                        }
                        pType[j].Projects = projects;
                    }

                gdata[i].ProjectType = pType;
            }

            ganttData = gdata;
            return ganttData; ;
        }

这里是递归函数

    private IEnumerable<SubProjectDto> GetActivitiesForActivityPerson(IEnumerable<SubProjectDto> children, Guid? personId)
    {
        var subProjects = children.CopySubProjectDtoEnumerable().ToList();

        for (var i = 0; i < subProjects.Count; i++)
        {
            var acts = subProjects[i].Activities.CopyActivityDtoEnumerable().ToList();

            acts.RemoveAll(activity => activity.ActivityPersons.All(person => person.PersonID != personId));

            subProjects[i].Activities = acts;

            if(subProjects[i].Children.Any())
                GetActivitiesForActivityPerson(subProjects[i].Children, personId);
        }

        children = subProjects;
        return children;
    }

当我单步执行递归函数时,return children 语句由修改后的activities 组成。但是,这行代码不包含修改后的activities,它包含赋值调用后的原始数据集。

projects[a].Children = GetActivitiesForActivityPerson(projects[a].Children, ganttFilterDataModel.PersonId);

如果有人想知道所有的复制方法是什么样的,它们只会返回DTO 的一个新实例。

例如

    public static IEnumerable<ProjectTypeDto> CopyProjectTypeDtoEnumerable(this IEnumerable<ProjectTypeDto> projectTypes)
    {
        return projectTypes.Select(x => new ProjectTypeDto
        {
            ProjectTypeId = x.ProjectTypeId,
            Description = x.Description,
            RowId = x.RowId,
            Projects = x.Projects.CopyProjectDtosEnumerable()
        });
    }

【问题讨论】:

  • 是否愿意通过解释帮助我改进问题?

标签: c# linq for-loop recursion dto


【解决方案1】:

为了将来参考,请提交可执行的代码摘录。为了获得最佳结果,您希望人们能够将您的问题代码直接复制粘贴到他们的 IDE 中进行使用。

此外,代码非常复杂。它简化为:

using System;
using System.Collections.Generic;
using System.Linq;

namespace StackOverflow_LoopMadness
{
    class Program
    {
        static void Main(string[] args)
        {
            // ???
        }

        private static IEnumerable<ProductLineDto> GetGanttDataByPerson(IEnumerable<ProductLineDto> ganttData, GanttFilterDto ganttFilterDataModel)
        {
            if (ganttFilterDataModel.PersonId == null)
                return ganttData;

            foreach (var pType in ganttData)
            {
                foreach (var project in pType.Projects)
                { 
                    project.Children = GetActivitiesForActivityPerson(project.Children, ganttFilterDataModel.PersonId);
                }
            }
            return ganttData;
        }

        private static IEnumerable<SubProjectDto> GetActivitiesForActivityPerson(IEnumerable<SubProjectDto> children, Guid? personId)
        {
            foreach (var subProject in children)
            {
                subProject.Activities = subProject.Activities.Where(a => a.ActivityPersons.All(person => person.PersonID != personId));

                if (subProject.Children.Any())
                {
                    GetActivitiesForActivityPerson(subProject.Children, personId);
                }
            }
            return children;
        }
    }

    class SubProjectDto
    {
        public IEnumerable<Activity> Activities { get; internal set; }
        public IEnumerable<SubProjectDto> Children { get; internal set; }
    }

    class Activity
    {
        public IList<ActivityPerson> ActivityPersons { get; internal set; }
    }

    class ActivityPerson
    {
        public Guid? PersonID { get; internal set; }
    }

    class GanttFilterDto
    {
        public Guid PersonId { get; internal set; }
    }

    class ProductLineDto
    {
        public IList<Project> Projects { get; internal set; }
    }

    class Project
    {
        public IEnumerable<SubProjectDto> Children { get; set; }
    }
}

如您所见,将 for 循环与 foreach 循环交换会大大减少代码量并提高可读性。无关的副本列表已被删除。而且,我需要通过猜测创建6个数据类才能编译。

我放弃了为这个程序寻找合适的驱动程序。不过,我相信修改嵌套元素的问题已经解决了,因为编辑后的变量只能通过引用传递。

我认为您的问题源于对按值传递与引用传递的不完全理解,因此您对深拷贝的使用令人困惑。微软可以比我解释得更好,所以请查看这个link

【讨论】:

  • 谢谢,就是这样。我试图修改IEnuemerable,我也在调用递归函数而不将它分配给任何东西!
猜你喜欢
  • 2016-04-25
  • 2021-08-11
  • 2017-08-23
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 2023-01-25
  • 1970-01-01
  • 2019-08-07
相关资源
最近更新 更多