C# 检索复杂列表中特定类型的所有嵌套对象的有效方法

C# 检索复杂列表中特定类型的所有嵌套对象的有效方法,c#,list,C#,List,我试图弄清楚如何在包含其他列表对象的列表对象中检索特定类型的对象,而不必手动遍历整个对象树 我知道我可以创建某种循环并检查每种对象类型,但我需要一种更高效、更美观的方法,比如LINQ语句或某种嵌套的lambda表达式或任何其他建议 我有一个类对象,它有一个列表成员,也有一个列表成员,也有一个列表成员,如下所示: 时间表类型 列表周期类型 列表条目 列出工作日 我想检索WorkDay类型的所有对象 下面是一个示例代码。我创建了一个示例对象,其中包含分布在树中的4个WorkDa

我试图弄清楚如何在包含其他列表对象的列表对象中检索特定类型的对象,而不必手动遍历整个对象树

我知道我可以创建某种循环并检查每种对象类型,但我需要一种更高效、更美观的方法,比如LINQ语句或某种嵌套的lambda表达式或任何其他建议

我有一个类对象,它有一个列表成员,也有一个列表成员,也有一个列表成员,如下所示:

  • 时间表类型
    • 列表周期类型
      • 列表条目
        • 列出工作日
我想检索WorkDay类型的所有对象

下面是一个示例代码。我创建了一个示例对象,其中包含分布在树中的4个WorkDay对象。如何有效地检索它们

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp
{
    public class TimesheetType
    {
        public List<PeriodType> PeriodTypes { get; set; }
    }

    public class PeriodType
    {
        public List<Entry> Entrys { get; set; }
    }

    public class Entry
    {
        public List<WorkDay> WorkDays { get; set; }
    }

    public class WorkDay
    {
        public DateTime Date { get; set; }
        public double Hours { get; set; }
    }



    class Program
    {
        static void Main(string[] args)
        {
            TimesheetType timesheetType = CreateTimesheetTypeExample();

            // Get all WorkDay typed objects in the tree, should return a List<WorkDay> with 4 items in it
            //var allWorkDays = timesheetType.PeriodTypes.Select(...) 
        }

        private static TimesheetType CreateTimesheetTypeExample()
        {
            TimesheetType timesheetType = new TimesheetType
            {
                PeriodTypes = new List<PeriodType>()
                {
                    {
                        new PeriodType()
                    },
                    {
                        new PeriodType()
                    },
                    {
                        new PeriodType()
                    },
                }
            };

            timesheetType.PeriodTypes[0].Entrys = new List<Entry>()
            {
                {
                    new Entry()
                }
            };

            timesheetType.PeriodTypes[1].Entrys = new List<Entry>()
            {
                {
                    new Entry()
                }
            };

            timesheetType.PeriodTypes[2].Entrys = new List<Entry>()
            {
                {
                    new Entry()
                }
            };

            timesheetType.PeriodTypes[0].Entrys[0].WorkDays = new List<WorkDay>(1)
            {
                new WorkDay() { Date = DateTime.Parse("2020-01-01"), Hours = 3 },
                new WorkDay() { Date = DateTime.Parse("2020-01-02"), Hours = 6 }
            };

            timesheetType.PeriodTypes[2].Entrys[0].WorkDays = new List<WorkDay>(1)
            {
                new WorkDay() { Date = DateTime.Parse("2020-01-03"), Hours = 12 },
                new WorkDay() { Date = DateTime.Parse("2020-01-04"), Hours = 24 }
            };

            return timesheetType;
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
名称空间控制台
{
公共类时间表类型
{
公共列表周期类型{get;set;}
}
公共类周期类型
{
公共列表入口{get;set;}
}
公开课入学
{
公共列表工作日{get;set;}
}
公课工作日
{
公共日期时间日期{get;set;}
公共双小时{get;set;}
}
班级计划
{
静态void Main(字符串[]参数)
{
TimesheetType TimesheetType=CreateTimesheetTypeExample();
//获取树中所有WorkDay类型的对象时,应返回一个包含4项的列表
//var allWorkDays=timesheetType.PeriodTypes.Select(…)
}
私有静态时间表类型CreateTimesheetTypeExample()
{
TimesheetType TimesheetType=新的时间表类型
{
PeriodTypes=新列表()
{
{
新PeriodType()
},
{
新PeriodType()
},
{
新PeriodType()
},
}
};
timesheetType.PeriodTypes[0]。Entrys=新列表()
{
{
新条目()
}
};
timesheetType.PeriodTypes[1]。Entrys=new List()
{
{
新条目()
}
};
timesheetType.PeriodTypes[2]。Entrys=新列表()
{
{
新条目()
}
};
时间表类型。周期类型[0]。入口[0]。工作日=新列表(1)
{
new WorkDay(){Date=DateTime.Parse(“2020-01-01”),Hours=3},
new WorkDay(){Date=DateTime.Parse(“2020-01-02”),Hours=6}
};
timesheetType.PeriodTypes[2]。条目[0]。工作日=新列表(1)
{
new WorkDay(){Date=DateTime.Parse(“2020-01-03”),Hours=12},
newworkday(){Date=DateTime.Parse(“2020-01-04”),Hours=24}
};
返回时间表类型;
}
}
}

假设
周期类型
条目
工作日
(因此所有列表)永远不会为空(但可以为空),那么两个
SelectMany
就可以做到这一点:

var allWorkDays = timesheetType.PeriodTypes
    .SelectMany(c => c.Entrys)
    .SelectMany(c => c.WorkDays).ToList();
SelectMany
展平嵌套列表,这正是您想要做的

在您的示例中,虽然列表可以为null,但您需要过滤掉null:

var allWorkDays = timesheetType.PeriodTypes.
    Where(c => c.Entrys != null).SelectMany(c => c.Entrys)
   .Where(c => c.WorkDays != null).SelectMany(c => c.WorkDays)
   .ToList();
或者像这样:

var allWorkDays = timesheetType.PeriodTypes
    .SelectMany(c => c.Entrys ?? new List<Entry>())
    .SelectMany(c => c.WorkDays ?? new List<WorkDay>())
    .ToList();
var allWorkDays=timesheetType.PeriodTypes
.SelectMany(c=>c.Entrys??新列表())
.SelectMany(c=>c.WorkDays??新列表())
.ToList();

使用linq并不能让它在任何想象中都更高效。方便吗?当然无论如何,循环都发生在某个地方,某个地方是Linq。太棒了!正是我要找的!