C#LinQSelectMany中文详解-Chinar-Linq语法大全

Chinar blog www.chinar.xin

SelectMany中文详解


本文提供全流程,中文翻译

助力快速理解 SelectMany 具体用途,4重载分析

为初学者节省宝贵的时间,避免采坑!

Chinar —— 心分享、心创新!

我们的初衷是将一种简单的生活方式带给世人

使有限时间 具备无限可能

Chinar 教程效果:

在这里插入图片描述----------


全文高清图片,点击即可放大观看 (很多人竟然不知道)


1 Intro —— 简介


Select 非常简单,将序列中选定的类型,返回一个新的集合
SelectMany 如其字面意思:选择许多

就是在 Select 的基础上,同时选定多个,返回多个而已

SelectMany 很多初学者并非完全理解,致使其使用率不高。

其实SelectMany 是一个非常实用的功能,可大量减少我们的代码量。

对数据进行查询时,可同时返回多项自定义类型,对数据的可控性非常高。

光说概念,呲牛逼。这显然不是 我 Chinar 的教程风格。

我们直接举个例子


2 Data —— 数据类


为了便于理解,先来一个数据类。下边几个重载,都用这一个数据进行说明

通用数据类

为避免初学者,被循环给绕晕

这里命名方式采用A B C 、One Two Three便于区分。 层级由外到内

one 第一层 ---------- A1

two 第二层 ---------- A2

three 第三层 ----------

举个例子

数据类

/// <summary>
/// 第一层:老爹
/// </summary>
public class One
{
    public string    Name;    //名字
    public int       Age;     //年龄
    public List<Two> TwoList; //儿子


    public One(string name, int age, List<Two> twoList)
    {
        Name    = name;
        Age     = age;
        TwoList = twoList;
    }
}


/// <summary>
/// 第二层:儿子
/// </summary>
public class Two
{
    public string      Name;      //名字
    public int         Age;       //年龄
    public List<Three> ThreeList; //儿子


    public Two(string name, int age, List<Three> threeList)
    {
        Name      = name;
        Age       = age;
        ThreeList = threeList;
    }


    public override string ToString()
    {
        return $"{nameof(Name)}: {Name}, {nameof(Age)}: {Age}, {nameof(ThreeList)}: {ThreeList}";
    }
}


/// <summary>
/// 第三层:孙子
/// </summary>
public class Three
{
    public int Age;   //年龄
    public int Score; //分数


    public Three(int age, int score)
    {
        Age   = age;
        Score = score;
    }


    public override string ToString()
    {
        return $"{nameof(Age)}: {Age}, {nameof(Score)}: {Score}";
    }
}

添加数据信息

List<One> ones = new List<One> //第一层:列表
{
    new One("A1", 40, new List<Two> //第二层:0
    {
        new Two("A2_0", 20,   new List<Three> {new Three(10, 100)}), //第三层
        new Two("A2_1", 200,  new List<Three> {new Three(10, 100)}), //第三层
        new Two("A2_2", 2000, new List<Three> {new Three(10, 100)})  //第三层
    }),
    new One("B1", 50, new List<Two>//第二层:1
    {
        new Two("B2", 30, new List<Three> {new Three(14, 70)})
    }),
    new One("C1", 70, new List<Two>//第二层:2
    {
        new Two("C2_0", 50, new List<Three> {new Three(25, 80)}),
        new Two("C2_1", 50, new List<Three> {new Three(25, 80)})
    }),
    new One("D1", 80, new List<Two>//第二层:3
    {
        new Two("D2", 60, new List<Three> {new Three(40, 50)})
    }),
};

3 Parameter 1 —— 重载1:1个参数


别看很复杂的样子,其实要点是:对 IEnumerable source,接口类型, 扩展函数/方法

IEnumerable SelectMany<TSource, TResult>(this IEnumerable source,
Func<TSource, IEnumerable<TResult>> selector );

传入参数为:一个 Func 委托类型

对数据源TSource处理,返回一个 IEnumerable <TResult >集合

举个例子

IEnumerable<List<Two>> onesSelect     = ones.Select(_ => _.TwoList);     //Select 返回 List<Two>
IEnumerable<Two>       onesSelectMany = ones.SelectMany(_ => _.TwoList); //第一个重载:返回 Two
foreach (var v in onesSelect)
{
    Console.WriteLine(v); //v=List<Two>
}

Console.WriteLine("----------------------------");
foreach (var v in onesSelectMany)
{
    Console.WriteLine(v); //v=Two
}

打印输出

在这里插入图片描述


4 Parameter 2 —— 重载2:2个参数


别看很复杂的样子,其实要点是:对 IEnumerable source,接口类型, 扩展函数/方法

IEnumerable SelectMany<TSource, TResult>(this IEnumerable source,
Func<TSource, IEnumerable<TResult>> selector );

传入参数为:一个 Func 委托类型

对数据源TSource处理,返回一个 IEnumerable <TResult >集合

举个例子

  #region 重载 2

            Console.WriteLine("----------重载 二 ------------");
            //var onesSelectMany2 = ones.SelectMany((a, b) =>
            //    a.TwoList.Select(_ =>
            //    {
            //        _.Name = b + "---" + _.Name;
            //        return _;
            //    }));

            //这里的 index 指的是 List<One> ones 中对象的索引
            IEnumerable<string> onesSelectMany2 = ones.SelectMany((one, index) => one.TwoList.Select(_ => "索引:" + index + "--名字:" + _.Name));
            foreach (var v in onesSelectMany2)
            {
                Console.WriteLine(v); //v=String
            }

            #endregion
            #region 重载 3

            Console.WriteLine("----------重载 三 ------------");
            var onesSelectMany3 = ones.SelectMany(one => one.TwoList, (one, two) => new {one.Name, two.Age}); //返回匿名类型: 1级的名字,2级的年龄
            //var onesSelectMany3 = ones.SelectMany(one => one.TwoList, (one, two) => new Dictionary<string, int> {{ one.Name, two.Age } });//可自定义返回类型
            foreach (var v in onesSelectMany3)
            {
                Console.WriteLine(v); //v=匿名类型
            }

            #endregion
            #region 重载 4

            Console.WriteLine("----------重载 三 ------------");
            var onesSelectMany4 = ones.SelectMany((one, index) => one.TwoList.Select(_ => "索引:" + index + "--名字:" + _.Name), (one, two) => new {one.Name, two}); //返回匿名类型: 1级的名字,2级的年龄
            //var onesSelectMany3 = ones.SelectMany(one => one.TwoList, (one, two) => new Dictionary<string, int> {{ one.Name, two.Age } });//可自定义返回类型
            foreach (var v in onesSelectMany4)
            {
                Console.WriteLine(v); //v=匿名类型
            }

            #endregion
            Console.ReadLine();

打印输出

在这里插入图片描述


支持

May Be —— 开发者,总有一天要做的事!


拥有自己的服务器,无需再找攻略

Chinar 提供一站式《零》基础教程

使有限时间 具备无限可能!

先点击领取 —— 阿里全产品优惠券 (享受最低优惠)


Chinar 免费服务器、建站教程全攻略!( Chinar Blog )


Chinar

END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: [email protected]

对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章