using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Xunit; using LinqStudy; namespace LinqStudy.Test.LinqToObject { /// <summary> /// 投影操作符 /// 投影:遍历序列中的元素,将元素由一种类型转换为另一种类型的操作,并返回由转换后元素组成的新序列。 /// 即是:IEnumerable<TSource> => IEnumerable<TResult> /// </summary> public class ProjectiveTest { /// <summary> /// Select投影:简单投影,一对一 /// </summary> [Fact] public void Select_Test() { // Arrange var persons = PersonManager.GetPersons(); // Act var maps = persons.Select(p=>p.Age).ToList(); // Assert Assert.IsType<List<int>>(maps); } /// <summary> /// 投影为匿名类 /// </summary> [Fact] public void Select_Anonymous_Test() { // Arrange var persons = PersonManager.GetPersons(); // Act var maps = persons.Select(p=>new {Id=p.Id, Node=$"姓名{p.Name},年龄{p.Age}."}).ToList(); // Assert Assert.IsNotType<List<Person>>(maps); } /// <summary> /// 投影传入索引(序号)参数 /// </summary> [Fact] public void Select_Index_Test() { var persons = PersonManager.GetPersons(); var maps = persons.Select((query,index)=> new KeyValuePair<int, Person>(index,query)).ToList(); var indexs = persons.Select((query, index) => index).ToList(); Assert.IsType<List<KeyValuePair<int, Person>>>(maps); Assert.Equal(0,indexs[0]); } /// <summary> /// 将序列的每个元素投影到 IEnumerable<TResult> 并将结果序列合并为一个序列。 /// </summary> /// <remarks> /// SelectMany:复合投影,一对多,合并多到一个集合。 /// 枚举源序列,将源序列每一项投影为新的集合,合并所有新集合为一个可枚举序列,做为返回值; /// 提供了将多个 from子句组合起来的功能,它将每个对象的结果合并成单个可枚举序列。 /// </remarks> [Fact] public void SelectMany_Test() { var employees = new List<Employee>() { new Employee(){Id=1,Name="小明",Emails=new List<string>(){ "abc@163.com", "acd@163.com", "ade@163.com" } }, new Employee(){Id=2,Name="大壮",Emails=new List<string>(){ "bbc@163.com", "bcd@163.com", "bde@163.com" } }, new Employee(){Id=3,Name="周羊",Emails=new List<string>(){ "cbc@163.com", "ccd@163.com", "cde@163.com" } }, new Employee(){Id=4,Name="承承",Emails=new List<string>(){ "dbc@163.com", "dcd@163.com", "dde@163.com" } }, new Employee(){Id=5,Name="东升",Emails=new List<string>(){ "ebc@163.com", "ecd@163.com", "ede@163.com" }}, }; var maps = employees.SelectMany(q=>q.Emails).ToList(); Assert.IsType<List<string>>(maps); Assert.Equal(15, maps.Count); } /// <summary> /// 将序列的每个元素投影到 IEnumerable<TResult>,并将结果序列合并为一个序列。每个源元素的索引用于该元素的投影表。 /// </summary> /// <remarks> /// 添加一个对源枚举的索引而已。索引从0开始,最大为TSource.Count-1 /// </remarks> [Fact] public void SelectMany_Index_Test() { var employees = new List<Employee>() { new Employee(){Id=1,Name="小明",Emails=new List<string>(){ "abc@163.com", "acd@163.com", "ade@163.com" } }, new Employee(){Id=2,Name="大壮",Emails=new List<string>(){ "bbc@163.com", "bcd@163.com", "bde@163.com" } }, new Employee(){Id=3,Name="周羊",Emails=new List<string>(){ "cbc@163.com", "ccd@163.com", "cde@163.com" } }, new Employee(){Id=4,Name="承承",Emails=new List<string>(){ "dbc@163.com", "dcd@163.com", "dde@163.com" } }, new Employee(){Id=5,Name="东升",Emails=new List<string>(){ "ebc@163.com", "ecd@163.com", "ede@163.com" }}, }; var maps = employees.SelectMany((q, idx) => { q.Emails.Add(idx.ToString()); return q.Emails; }).ToList(); Assert.IsType<List<string>>(maps); Assert.Equal(20, maps.Count); } /// <summary> /// 将序列的每个元素投影到 IEnumerable<TCollection>,并将结果序列合并为一个序列,并对其中每个元素调用结果选择器函数。 /// </summary> /// <remarks> /// 自定义结果项,类似Cross JOIN /// </remarks> [Fact] public void SelectMany_TCollection_Test() { var employees = new List<Employee>() { new Employee(){ Id=1,Name="小明",Emails=new List<string>(){ "a1@163.com", "a2@163.com", "a3@163.com" } }, new Employee(){ Id=2,Name="大壮",Emails=new List<string>(){ "b1@163.com", "b2@163.com", "b3@163.com" } }, new Employee(){ Id=3,Name="周羊",Emails=new List<string>(){ "c1@163.com", "c2@163.com", "c3@163.com" } }, new Employee(){ Id=4,Name="承承",Emails=new List<string>(){ "d1@163.com", "d2@163.com", "d3@163.com" } }, new Employee(){ Id=5,Name="东升",Emails=new List<string>(){ "e1@163.com", "e2@163.com", "e3@163.com" } }, }; var maps = employees.SelectMany((employee)=> employee.Emails,(person,email)=> new { Name=person.Name,Email=email}).ToList(); Assert.Equal(15, maps.Count); } /// <summary> /// 将序列的每个元素投影到 IEnumerable<TCollection>,并将结果序列合并为一个序列,并对其中每个元素调用结果选择器函数。 /// 每个源元素的索引用于该元素的中间投影表。 /// </summary> /// <remark> /// 自定义结果项,类似Cross JOIN /// </remark> [Fact] public void SelectMany_TCollection_Index_Test() { var employees = new List<Employee>() { new Employee(){ Id=1,Name="小明",Emails=new List<string>(){ "a1@163.com", "a2@163.com", "a3@163.com" } }, new Employee(){ Id=2,Name="大壮",Emails=new List<string>(){ "b1@163.com", "b2@163.com", "b3@163.com" } }, new Employee(){ Id=3,Name="周羊",Emails=new List<string>(){ "c1@163.com", "c2@163.com", "c3@163.com" } }, new Employee(){ Id=4,Name="承承",Emails=new List<string>(){ "d1@163.com", "d2@163.com", "d3@163.com" } }, new Employee(){ Id=5,Name="东升",Emails=new List<string>(){ "e1@163.com", "e2@163.com", "e3@163.com" } }, }; var maps = employees.SelectMany ( (employee, idx) => { return new List<Employee>() { new Employee() { Id = employee.Id, Name = employee.Name + "_" + idx, Emails = employee.Emails } }; }, (person,email) => new { Name = email.Name, Email = email.Emails } ) .ToList(); Assert.Equal(5, maps.Count); } [Fact] public void Test() { var cc= DocDemo(""); } /// <summary> /// Doc示例 /// </summary> /// <param name="aa">参数</param> /// <exception cref="ArgumentNullException"> /// ArgumentNullException /// </exception> /// <example>DecDemo("dsfsadf")</example> /// <seealso cref="SortedDictionary{TKey, TValue}"/> /// <returns>参数+“-”</returns> private string DocDemo(string aa) { return aa + "-"; } } }