演变
委托→lambda→LINQ
LINQ可以让数据处理变得简单
使用
委托
委托是可以指向方法的类型,调用委托变量执行的就是变量指向的方法。
自己定义委托
delegate void D1();
.Net中自定义了泛型委托Action(无返回值)和Func(有返回值),所以一般不用自定义委托类型
static void Main(string[] args)
{
Console.WriteLine("Hello, World!");
D1 d = F1;
d();
Action ac = F1;
ac();
Action<string> ac2 = F1;
ac2("123");
Func<int, int, int> f1 = add;
f1(1, 1);
}
static void F1()
{
Console.WriteLine("我是F1");
}
static void F1(string s)
{
Console.WriteLine($"我是F1的重载并附带参数{s}");
}
static int add(int n1, int n2)
{
Console.WriteLine(n1 + n2);
return n1 + n2;
}
委托变量不仅可以指向普通方法,还可以指向匿名方法
Action unName = delegate ()
{
Console.WriteLine("我是匿名方法");
};
unName();
Lambda
匿名方法可以写成lambda表达式
Func<int, int, int> reduce = (n1, n2) =>
{
Console.WriteLine(n1 - n2);
return n1 - n2;
};
reduce(10, 1);
lambda表达式可以省略参数类型,它可以根据委托的数据类型推出。如果方法体内只有一行代码,大括号也可以省略(无论有无返回值),如果只有一个参数,传参的小括号也可以省略。
Func<string, string> rename = s => $"测试{s}";
Console.WriteLine(rename("12345"));
LINQ
LINQ中提供了很多集合的扩展方法,配合lambda能简化处理。
所有实现了IEnumberable<T>接口的都可以使用LINQ扩展方法,如:
数组、List、Dictionary、Set...
int[] nums = new int[] {555, 3, 4, 5, 565, 234, 2345};
IEnumerable<int> res = nums.Where(n => n > 10);
以下是一些常用的LINQ扩展方法
Where 用于筛选符合条件,返回集合
IEnumerable<Employee> res = list.Where(n => n.Age > 18);
Count 用于统计,返回int类型的数字,会全部遍历
int count = list.Count(e => e.Age > 20)
Any 查询是否至少有一条符合,返回bool类型,不会全部遍历,有符合就直接返回
bool flag = list.Any(e => e.Age > 20);
Single 有且只有一条满足要求的数据,若有多条数据符合直接报错
报错信息为:
System.InvalidOperationException:“Sequence contains more than one element”
Employee e1 = list.Where(e => e.Name.Equals("Jerry")).Single();
Employee e2 = list.Single(e => e.Name.Equals("Jerry"));
SingleOrDefault 最多只有一条满足要求的数据,没有就返回默认值null
Employee e2 = list.SingleOrDefault(e => e.Name.Equals("Jerry"));
First 至少有一条,返回第一条,若没有一条符合则报错
报错信息为:
System.InvalidOperationException:“Sequence contains no matching element”
Employee e3 = list.First(e => e.Age > 30);
FirstOrDefault 返回第一条或默认值
Employee e4 = list.FirstOrDefault(e => e.Age > 30);
OrderBy 排序 | ThenBy 然后排序
IEnumerable<Employee> el1 = list.OrderBy(e => e.Name[0]).ThenBy(e => e.Age);
OrderByDescending 倒叙排序 | ThenByDescending 然后倒叙排序
IEnumerable<Employee> el2 = list.OrderByDescending(e => e.Name[0]).ThenByDescending(e => e.Age);
Skip | Take 跳过部分数据 | 取部分数据
IEnumerable<Employee> el3 = list.Skip(3).Take(2);
Max 最大值 | Min 最小值 | Average 平均值 | Sum 求和 | Count 统计
int max = list.Max(e => e.Age);
GroupBy 分组
IEnumerable<IGrouping<int, Employee>> items = list.GroupBy(e => e.Age);
Select 投影
var items1 = list.Select(e => new {Name = e.Name, Age = e.Age});
IEnumerable<Employee> items2 = list.Select(e => new Employee {Name = e.Name, Age = e.Age});
除了使用链式编程的写法之外,还可以使用查询语句的写法,编译出来的结果是一样的
var items4 = list.Where(e => e.Salary > 3000).OrderBy(e => e.Age)
.Select(e => new { e.Age, e.Name,Sex = e.Gender ? "男" : "女" });
var items5 = from e in list where e.Salary > 3000
select new { e.Age, e.Name, Sex = e.Gender ? "男" : "女" };
部分数据附录
Employee.cs
namespace test
{
class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public bool Gender { get; set; }
public int Salary { get; set; }
public override string ToString()
{
return $"Id={Id},Name={Name},Age={Age},Gender={Gender},Salary={Salary}";
}
}
}
Program.cs
namespace test
{
class Program
{
static void Main(string[] args)
{
List<Employee> list = init();
}
static List<Employee> init()
{
List<Employee> list = new List<Employee>();
list.Add(new Employee {Id = 1, Name = "Jerry", Age = 28, Gender = true, Salary = 5000 });
list.Add(new Employee {Id = 2, Name = "Jim", Age = 33, Gender = true, Salary = 3000 });
list.Add(new Employee {Id = 3, Name = "Lily", Age = 35, Gender = false, Salary = 9000 });
list.Add(new Employee {Id = 4, Name = "Lucy", Age = 16, Gender = false, Salary = 2000 });
list.Add(new Employee {Id = 5, Name = "Kimi", Age = 25, Gender = true, Salary = 1000 });
list.Add(new Employee {Id = 6, Name = "Nancy", Age = 35, Gender = false, Salary = 8000 });
list.Add(new Employee {Id = 7, Name = "Zack", Age = 35, Gender = true, Salary = 8500 });
list.Add(new Employee {Id = 8, Name = "Jack", Age = 33, Gender = true, Salary = 8000 });
return list;
}
}
}