.Net【基础回顾】泛型逆变协变和Linq
泛型
Generic
允许您延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候。
逆变与协变
协变就是父类转变为子类,逆变就是子类转变为父类。
通过在泛型参数上使用in
或out
关键字,可以得到逆变或协变的能力
-
in
逆变 -
out
协变
IEnumerable<out T> //接口
Action<in T> //委托
Func<out TResult> //委托
IReadOnlyList<out T> //接口
IReadOnlyCollection<out T> //接口
Linq
using System.Linq;
AsEnumerable()
- 判断
Any()
All()
- 筛选
Where()
Select()
SelectMany()
List<Bouquet> bouquets = new List<Bouquet>()
{
new Bouquet { Flowers = new List<string> { "sunflower", "daisy", "daffodil", "larkspur" }},
new Bouquet{ Flowers = new List<string> { "tulip", "rose", "orchid" }},
new Bouquet{ Flowers = new List<string> { "gladiolis", "lily", "snapdragon", "aster", "protea" }},
new Bouquet{ Flowers = new List<string> { "larkspur", "lilac", "iris", "dahlia" }}
};
// *********** Select ***********
IEnumerable<List<string>> query1 = bouquets.Select(bq => bq.Flowers);
// ********* SelectMany *********
IEnumerable<string> query2 = bouquets.SelectMany(bq => bq.Flowers);
- 排序
OrderBy()
OrderByDescending()
ThenBy()
ThenByDescending()
Reverse()
- 连接
Join() // 对应sql中的inner join
GroupJoin() //对应sql中的left join
var sg = db.Users.Join(db.Departments, u => u.DepartmentId, d => d.DepartmentId, (u,d) => new { u, d }).Select(o=>o).ToList();
//注意:这里将只显示用户里DepartmentId和部门表里DepartmentId相等的信息,如果用户没有部门ID则此条用户信息不会显示
var sg = db.Users.GroupJoin(db.Departments, u => u.DepartmentId, d => d.DepartmentId, (u,d) => new { u, d }).Select(o=>o).ToList();
// 注意:上面将返回所用用户信息和对应的部门信息(即用户部门ID信息缺少,那么用户列表也会显示)
- 分组聚合
GroupBy()
Sum()
Max()
Min()
Average()
Count
longCount
- 集合运算
Contact() //两个集合合并成一个新的集合
Union() //并集 去重的
Except() //差集计算 list去除共同部分
Intersect() //交集计算 注意判断元素相等
- 序列运算
First() //找不到会抛出异常
FirstOrDefault() //找不到返回NULL
Last()
LastOrDefault()
ElementAt()
ElementAtOrDefault()
Take()
TakeWhile() //一直提取到条件为止,条件之后的数据不再抽出
public void TakeWhileTest()
{
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
//在这里需要注意.使用TakeWhile获取小于6的元素,是从第一个元素开始,
//一直到不满足其小于6这个条件为止.也就是执行到和9这个元素比较后,就结束比较了
//可以想象一下执行过程.
//5<6=true;4<6=true;1<6=true;3<6=true
//9<6=false; 这里就停止继续比较了
var firstNumbersLessThan6 = numbers.TakeWhile(n => n < 6);
Console.WriteLine("First numbers less than 6:");
foreach (var n in firstNumbersLessThan6)
{
Console.WriteLine(n);
}
}
//结果
// 5
// 4
// 1
// 3
Skip()
SkipWhile() //从不符合条件的数据开始取当前和之后所有数据
public void SkipWhileTest()
{
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
//这里和TakeWhiel又有些不一样。
var allButFirst3Numbers = numbers.SkipWhile(n => n < 6);
Console.WriteLine("结果:");
foreach (var n in allButFirst3Numbers)
{
Console.WriteLine(n);
}
}
//结果
// 9
// 8
// 6
// 7
// 2
// 0
- 类型转换
ToArray()
ToDictionary()
ToList()
ToLookUp()
- 累加函数 Aggregate
static void Main()
{
int[] array = { 1, 2, 3, 4, 5 };
int result = array.Aggregate((a, b) => b + a);//累加
// 1 + 2 = 3
// 3 + 3 = 6
// 6 + 4 = 10
// 10 + 5 = 15
Console.WriteLine(result);
result = array.Aggregate((a, b) => b * a);//阶乘
// 1 * 2 = 2
// 2 * 3 = 6
// 6 * 4 = 24
// 24 * 5 = 120
Console.WriteLine(result);
}
//输出结果:
//15
//120