using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Xunit; namespace LinqStudy.Test.LinqToObject { /// /// Sets 集合操作符 /// 注意:集合操作为 “延迟执行”,数据源为null时均引发异常。 /// public class SetsTest { #region Distinct /// /// Distinct:元素去重;延迟执行。 /// 注意:值类型可以直接去重;引用类型比较的是引用而不是对象本身的属性等,可以提供自定义比较器。 /// [Fact] public void Distinct_Test() { List array = new List() { 1, 2, 2, 3, 3, 3 }; var distinctItem = array.Distinct(); var expected = new List() { 1, 2, 3 }; Assert.Equal(expected, distinctItem); } /// /// 引用类型:剔除同一个引用的重复项。 /// [Fact] public void Distinct_Reference_Yes_Test() { var p1 = new Person() { Id = 2, Name = "小龙女", Age = 28 }; var p2 = new Person() { Id = 4, Name = "杨过", Age = 32 }; List peoples = new List(); peoples.Add(p1); peoples.Add(p2); //添加对同一对象的多次引用 peoples.Add(p1); peoples.Add(p2); var totalCount = peoples.Count(); var distinctCount = peoples.Distinct().Count(); Assert.Equal(4, totalCount); Assert.Equal(2, distinctCount); } [Fact] public void Distinct_Reference_No_Test() { List peoples = new List() { new Person() { Id = 1, Name = "小龙女", Age = 28 }, new Person() { Id = 1, Name = "小龙女", Age = 28 }, }; //虽然1、2两项对象属性完命相同,但是两个不同的对象(new两次),所以不是“重复项” //去重后仍然是2项 var distinctCount = peoples.Distinct().Count(); Assert.Equal(2, distinctCount); } /// /// 延迟执行 /// [Fact] public void Distinct_Daley_Test() { List array = new List() { 1, 2, 2, 3, 3, 3 }; var distinctItem = array.Distinct(); array.Add(5); var expected = new List() { 1, 2, 3, 5 }; Assert.Equal(expected, distinctItem); } /// /// 重载:自定义比较器 /// [Fact] public void Distinct_compare_Test() { List peoples = new List() { new Person(){ Id=1, Name="小龙女", Age=28}, new Person(){ Id=1, Name="我不是龙女", Age=68}, }; var distinctItem = peoples.Distinct(new PersonEqualityComparerById()); //虽然两项只有Id属性相等,其它属性均不同; //但是因为自定义比较器内部,只比较Id即只要Id相同就认为同一对象。 //所以去重后,只有一项(第一项,第二项被认为是重复项,被去除)。 var distinctCount = distinctItem.Count(); var expected = 1; Assert.Equal(expected, distinctCount); } #endregion #region Union /// /// Union:取两个序列的并集,并去除重复项。 /// 与SQL比较相似;Concat不去除重复项。 /// [Fact] public void Union_Test() { var p1 = new Person() { Id = 1, Name = "杨过", Age = 32 }; var p2 = new Person() { Id = 2, Name = "小龙女", Age = 28 }; var p3 = new Person() { Id = 3, Name = "云花公主", Age = 16 }; List peoples1 = new List() { p1, p2, }; List peoples2 = new List() { p1, p3, }; var act = peoples1.Union(peoples2); //因为"杨过"是重复的,所有总共有3项 var totalCount = act.Count(); Assert.Equal(3, totalCount); } /// /// Union: 对同一数据源两次查询后,两次结果Union /// 注意:同一数据源多次查询形成的序列项,均是对同一对象的引用。 /// 项里保存的是引用地址,非对象本身。 /// [Fact] public void Union_UseQuery_Test() { List peoples = new List() { new Person(){ Id=1, Name="张三丰", Age=230}, new Person(){ Id=2, Name="小龙女", Age=28}, new Person(){ Id=3, Name="云花公主", Age=16}, new Person(){ Id=4, Name="杨过", Age=32}, }; var peoples1 = peoples.Where(q => q.Id <= 3); var peoples2 = peoples.Where(q => q.Age < 230); var act = peoples1.Union(peoples2); //前3项 + 后3项- 重复2项=4项 var totalCount = act.Count(); Assert.Equal(4, totalCount); } /// /// Union重载: camparer /// [Fact] public void Union_camparer_Test() { var p1 = new Person() { Id = 1, Name = "杨过", Age = 32 }; var p2 = new Person() { Id = 2, Name = "小龙女", Age = 28 }; var p3 = new Person() { Id = 2, Name = "我非龙女", Age = 77 }; List peoples1 = new List() { p1, p2, }; List peoples2 = new List() { p1, p3, }; var act = peoples1.Union ( peoples2, new PersonEqualityComparerById() ) .ToList(); //虽然P2和p3只有Id相同,其它不同;但自定义比较只看Id,所以P2和p3被认为是同一个对象。 //结果集为:p1+p2 var totalCount = act.Count(); Assert.Equal(2, totalCount); } /// /// 异常:ArgumentNullException /// [Fact] public void Union_ArgumentNullException_Test() { List peoples1 = null; List peoples2 = null; Action act = () => peoples1.Union ( peoples2 ); Assert.Throws(act); } #endregion #region Intersect /// /// Intersect: 取交集 /// [Fact] public void Intersect_Test() { var p1 = new Person() { Id = 1, Name = "杨过", Age = 32 }; var p2 = new Person() { Id = 2, Name = "小龙女", Age = 28 }; var p3 = new Person() { Id = 3, Name = "云花公主", Age = 16 }; List peoples1 = new List() { p1,p2, }; List peoples2 = new List() { p1,p3, }; var intesectItem = peoples1.Intersect(peoples2); var itemCount = intesectItem.Count(); Assert.Equal(1, itemCount); } /// /// 引用类型:使用 /// [Fact] public void Intersect_Reference_Test() { List peoples1 = new List() { new Person(){ Id=1, Name="杨过", Age=32}, new Person(){ Id=2, Name="小龙女", Age=28}, }; List peoples2 = new List() { new Person(){ Id=2, Name="小龙女", Age=28}, new Person(){ Id=3, Name="云花公主", Age=16}, }; //虽然两个“小龙女”属性相同,但不是一个对象,没有交集。 var intesectItem = peoples1.Intersect(peoples2); Assert.Empty(intesectItem); } /// /// 重载:自定义比较器 comparer /// [Fact] public void Intersect_comparer_Test() { List peoples1 = new List() { new Person(){ Id=1, Name="杨过", Age=32}, new Person(){ Id=2, Name="小龙女", Age=28}, }; List peoples2 = new List() { new Person(){ Id=2, Name="小龙女", Age=28}, new Person(){ Id=3, Name="云花公主", Age=16}, }; //虽然两个“小龙女”属性相同,但不是一个对象,没有交集。 var intesectItem = peoples1.Intersect(peoples2, new PersonEqualityComparerById()); var intesctItemName = intesectItem.First().Name; Assert.Equal("小龙女", intesctItemName); } #endregion #region Intersect /// /// Except: 从一个序列中排除另一个序列中的项。 /// [Fact] public void Except_Test() { var p1 = new Person() { Id = 1, Name = "杨过", Age = 32 }; var p2 = new Person() { Id = 2, Name = "小龙女", Age = 28 }; var p3 = new Person() { Id = 3, Name = "云花公主", Age = 16 }; List peoples1 = new List() { p1,p2, }; List peoples2 = new List() { p1,p3, }; var exceptItem = peoples1.Except(peoples2); var itemName = exceptItem.First().Name; Assert.Equal("小龙女", itemName); } /// /// 引用类型:使用 /// [Fact] public void Except_Reference_Test() { List peoples1 = new List() { new Person(){ Id=1, Name="杨过", Age=32}, new Person(){ Id=2, Name="小龙女", Age=28}, }; List peoples2 = new List() { new Person(){ Id=2, Name="小龙女", Age=28}, new Person(){ Id=3, Name="云花公主", Age=16}, }; var exceptItem = peoples1.Except(peoples2); var itemCount = exceptItem.Count(); Assert.Equal(2, itemCount); } /// /// 重载:自定义比较器 comparer /// [Fact] public void Except_comparer_Test() { List peoples1 = new List() { new Person(){ Id=1, Name="杨过", Age=32}, new Person(){ Id=2, Name="小龙女", Age=28}, }; List peoples2 = new List() { new Person(){ Id=2, Name="小龙女", Age=28}, new Person(){ Id=3, Name="云花公主", Age=16}, }; var exceptItem = peoples1.Except(peoples2, new PersonEqualityComparerById()); var iexcepItemName = exceptItem.First().Name; Assert.Equal("杨过", iexcepItemName); } #endregion #region Concat /// /// 串联操作 /// public class ConcatTest { /// /// Concat:将两个序列合并成一个序列,不去重。与Union不同。 /// public void Concat_Test() { List peoples1 = new List() { new Person(){ Id=2, Name="小龙女", Age=28}, new Person(){ Id=4, Name="杨过", Age=32}, }; List peoples2 = new List() { new Person(){ Id=2, Name="小龙女", Age=28}, new Person(){ Id=3, Name="云花公主", Age=16}, }; var concatAct = peoples1.Concat(peoples2); var totalCount = concatAct.Count(); Assert.Equal(4, totalCount); } } #endregion } }