|
|
|
|
using System;
|
|
|
|
|
using System.Collections;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using Xunit;
|
|
|
|
|
|
|
|
|
|
using System.Collections.Immutable;
|
|
|
|
|
|
|
|
|
|
namespace LinqStudy.Test.LinqToObject
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Sets 集合操作符
|
|
|
|
|
/// 注意:集合操作为 “延迟执行”,数据源为null时均引发异常。
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class SetsTest
|
|
|
|
|
{
|
|
|
|
|
#region Distinct
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Distinct:元素去重;延迟执行。
|
|
|
|
|
/// 注意:值类型可以直接去重;引用类型比较的是引用而不是对象本身的属性等,可以提供自定义比较器。
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Distinct_Test()
|
|
|
|
|
{
|
|
|
|
|
List<int> array = new List<int>() { 1, 2, 2, 3, 3, 3 };
|
|
|
|
|
|
|
|
|
|
var distinctItem = array.Distinct();
|
|
|
|
|
var expected = new List<int>() { 1, 2, 3 };
|
|
|
|
|
|
|
|
|
|
Assert.Equal(expected, distinctItem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 引用类型:剔除同一个引用的重复项。
|
|
|
|
|
/// </summary>
|
|
|
|
|
[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<Person> peoples = new List<Person>();
|
|
|
|
|
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<Person> peoples = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 延迟执行
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Distinct_Daley_Test()
|
|
|
|
|
{
|
|
|
|
|
List<int> array = new List<int>() { 1, 2, 2, 3, 3, 3 };
|
|
|
|
|
|
|
|
|
|
var distinctItem = array.Distinct();
|
|
|
|
|
|
|
|
|
|
array.Add(5);
|
|
|
|
|
|
|
|
|
|
var expected = new List<int>() { 1, 2, 3, 5 };
|
|
|
|
|
|
|
|
|
|
Assert.Equal(expected, distinctItem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 重载:自定义比较器
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Distinct_compare_Test()
|
|
|
|
|
{
|
|
|
|
|
List<Person> peoples = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// Union:取两个序列的并集,并去除重复项。
|
|
|
|
|
/// 与SQL比较相似;Concat不去除重复项。
|
|
|
|
|
///</summary>
|
|
|
|
|
[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<Person> peoples1 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
p1,
|
|
|
|
|
p2,
|
|
|
|
|
};
|
|
|
|
|
List<Person> peoples2 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
p1,
|
|
|
|
|
p3,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var act = peoples1.Union(peoples2);
|
|
|
|
|
|
|
|
|
|
//因为"杨过"是重复的,所有总共有3项
|
|
|
|
|
var totalCount = act.Count();
|
|
|
|
|
|
|
|
|
|
Assert.Equal(3, totalCount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// Union: 对同一数据源两次查询后,两次结果Union
|
|
|
|
|
/// 注意:同一数据源多次查询形成的序列项,均是对同一对象的引用。
|
|
|
|
|
/// 项里保存的是引用地址,非对象本身。
|
|
|
|
|
///</summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Union_UseQuery_Test()
|
|
|
|
|
{
|
|
|
|
|
List<Person> peoples = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// Union重载: camparer
|
|
|
|
|
///</summary>
|
|
|
|
|
[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<Person> peoples1 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
p1,
|
|
|
|
|
p2,
|
|
|
|
|
};
|
|
|
|
|
List<Person> peoples2 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// 异常:ArgumentNullException
|
|
|
|
|
///</summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Union_ArgumentNullException_Test()
|
|
|
|
|
{
|
|
|
|
|
List<Person> peoples1 = null;
|
|
|
|
|
List<Person> peoples2 = null;
|
|
|
|
|
|
|
|
|
|
Action act = () => peoples1.Union
|
|
|
|
|
(
|
|
|
|
|
peoples2
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
Assert.Throws<ArgumentNullException>(act);
|
|
|
|
|
}
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region Intersect
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// Intersect: 取交集
|
|
|
|
|
///</summary>
|
|
|
|
|
[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<Person> peoples1 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
p1,p2,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
List<Person> peoples2 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
p1,p3,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var intesectItem = peoples1.Intersect(peoples2);
|
|
|
|
|
var itemCount = intesectItem.Count();
|
|
|
|
|
|
|
|
|
|
Assert.Equal(1, itemCount);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// 引用类型:使用
|
|
|
|
|
///</sumaary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Intersect_Reference_Test()
|
|
|
|
|
{
|
|
|
|
|
List<Person> peoples1 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
new Person(){ Id=1, Name="杨过", Age=32},
|
|
|
|
|
new Person(){ Id=2, Name="小龙女", Age=28},
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
List<Person> peoples2 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
new Person(){ Id=2, Name="小龙女", Age=28},
|
|
|
|
|
new Person(){ Id=3, Name="云花公主", Age=16},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//虽然两个“小龙女”属性相同,但不是一个对象,没有交集。
|
|
|
|
|
var intesectItem = peoples1.Intersect(peoples2);
|
|
|
|
|
|
|
|
|
|
Assert.Empty(intesectItem);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// 重载:自定义比较器 comparer
|
|
|
|
|
///</sumaary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Intersect_comparer_Test()
|
|
|
|
|
{
|
|
|
|
|
List<Person> peoples1 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
new Person(){ Id=1, Name="杨过", Age=32},
|
|
|
|
|
new Person(){ Id=2, Name="小龙女", Age=28},
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
List<Person> peoples2 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// Except: 从一个序列中排除另一个序列中的项。
|
|
|
|
|
///</summary>
|
|
|
|
|
[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<Person> peoples1 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
p1,p2,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
List<Person> peoples2 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
p1,p3,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var exceptItem = peoples1.Except(peoples2);
|
|
|
|
|
var itemName = exceptItem.First().Name;
|
|
|
|
|
|
|
|
|
|
Assert.Equal("小龙女", itemName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// 引用类型:使用
|
|
|
|
|
///</sumaary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Except_Reference_Test()
|
|
|
|
|
{
|
|
|
|
|
List<Person> peoples1 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
new Person(){ Id=1, Name="杨过", Age=32},
|
|
|
|
|
new Person(){ Id=2, Name="小龙女", Age=28},
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
List<Person> peoples2 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// 重载:自定义比较器 comparer
|
|
|
|
|
///</sumaary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Except_comparer_Test()
|
|
|
|
|
{
|
|
|
|
|
List<Person> peoples1 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
new Person(){ Id=1, Name="杨过", Age=32},
|
|
|
|
|
new Person(){ Id=2, Name="小龙女", Age=28},
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
List<Person> peoples2 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
///<summary>
|
|
|
|
|
/// Concat:将两个序列合并成一个序列,不去重。与Union不同。
|
|
|
|
|
///<summary>
|
|
|
|
|
[Fact]
|
|
|
|
|
public void Concat_Test()
|
|
|
|
|
{
|
|
|
|
|
List<Person> peoples1 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
new Person(){ Id=2, Name="小龙女", Age=28},
|
|
|
|
|
new Person(){ Id=4, Name="杨过", Age=32},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
List<Person> peoples2 = new List<Person>()
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|