助力快速理解 SelectMany 的高级用法 为初学者节省宝贵的时间,避免采坑! |
我们的初衷是将一种简单的生活方式带给世人 使有限时间 具备无限可能 |
Chinar 教程效果:
1 Intro —— 简介
SelectMany对于初学者来讲,是一个比较难理解的函数。其内部逻辑,有点绕。
在使用上,对初学者来讲,尤其是容易懵逼…
但它的用途极其广泛,且极大的节省代码、提高代码可读性。
避免大量的循环代码
这里我以 4个例子,说明SelectMany的多种用法。
请大家仔细、耐心的看完。
1.1 Constructor ―― 构造函数
Wait —— 敬请期待
设置tag —— 格子=Grid;物品=Good;
/// <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}";
}
}
初始化,填入数据
为了便于大家理解,我用了
one、two、three 做为3层嵌套的子父类;
one 对应的数据值为: A、B、C、D
List<One> ones = new List<One> //第一层列表
{
new One("A1", 40, new List<Two> //第二层
{
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>
{
new Two("B2", 30, new List<Three> {new Three(14, 70)})
}),
new One("C1", 70, new List<Two>
{
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>
{
new Two("D2", 60, new List<Three> {new Three(40, 50)})
}),
};
2 Overload 1 —— 重载 1
我们来看下官方的代码注释:
//
// 摘要:
// 一个序列的每个元素投影 System.Collections.Generic.IEnumerable`1, ,并将合并为一个序列将结果序列。 每个源元素的索引用于该元素的投影表。
//
// 参数:
// source:
// 一个要投影的值序列。
//
// selector:
// 一个应用于每个源元素的转换函数;函数的第二个参数表示源元素的索引。
//
// 类型参数:
// TSource:
// 中的元素的类型 source。
//
// TResult:
// 返回的序列的元素的类型 selector。
//
// 返回结果:
// System.Collections.Generic.IEnumerable`1 其元素是一种一对多转换函数对输入序列中的每个元素调用的结果。
//
// 异常:
// T:System.ArgumentNullException:
// source 或 selector 为 null。
public static IEnumerable<TResult> SelectMany<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, IEnumerable<TResult>> selector);
懵逼不?这才是重载第一个
不要怕,有我,跟我来看个栗子
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
}
输出结果
可以看出明显区别。
SelectMany 作用:
Ones列表中的 每个元素 One 的实例,
每个 One 实例下都对应了几个 TwoList 列表
将每个 TwoList 列表中的的元素 Two ,重新组合成一个包含了所有 TwoList的大列表;
还不理解?没事,我给你们准备了张图。
支持
May Be —— 开发者,总有一天要做的事!
Chinar 提供一站式《零》基础教程 使有限时间 具备无限可能! |
Chinar 免费服务器、建站教程全攻略!( Chinar Blog )
本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究
对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: [email protected]
对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址