C# 匿名方法、Linq
1 匿名方法 lambda表达式
在我们之前学习委托的时候有一个求大于20岁的学生信息的功能,现在我们使用匿名方法优化下它:
学生类:
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
public Student(string name, int age, string email)
{
this.Name = name;
this.Age = age;
this.Email = email;
}
public Student() { }
}
初始化信息:
List<Student> students = new List<Student>();
students.Add(new Student("Oliver", 18, "123@qq.com"));
students.Add(new Student("小白", 19, "123@sina.com"));
students.Add(new Student("老K", 28, "123@163.com"));
students.Add(new Student("土豆", 16, "232@sina.com"));
students.Add(new Student("番茄", 33, "fanqie@qq.com"));
students.Add(new Student("小红", 22, "24424@163.com"));
students.Add(new Student("黎明", 18, "2232@126.com"));
students.Add(new Student("黄昏", 21, "huanghun@qq.com"));
匿名方法
使用委托的方式
var newList = students.MyWhere(this.GetAgeThan);//筛选年龄大于20的学生
Console.WriteLine(newList.Count());
GetAgeThan方法
bool GetAgeThan(Student s)
{
return s.Age > 20;
}
匿名方法1,将方法体直接写到参数中,传递给委托
var age = 20;
var newList = students.MyWhere(delegate (Student s)
{
return s.Age > age;//匿名方法可以访问方法外的变量
});//筛选年龄大于20的学生
Console.WriteLine(newList.Count());
匿名方法2:省略委托,使用=> 区别参数与方法体
var newList = students.MyWhere((Student s) =>
{
return s.Age > 20;
});//筛选年龄大于20的学生
Console.WriteLine(newList.Count());
匿名方法3:省略参数类型
var newList = students.MyWhere((s) => { return s.Age > 20; });//筛选年龄大于20的学生
Console.WriteLine(newList.Count());
匿名方法4:省略参数的括号
var newList = students.MyWhere(s => { return s.Age > 20; });//筛选年龄大于20的学生
Console.WriteLine(newList.Count());
匿名方法5:当方法体中只有一行时,可以省略方法体的括号与return关键字(是不是我们的Lambda表达式很像呢)
var newList = students.MyWhere(s => s.Age > 20);//筛选年龄大于20的学生
Console.WriteLine(newList.Count());
MyWhere方法
/// <summary>
/// 使用静态类加静态方法,直接调用
/// </summary>
public static class ExtendMethod
{
/// <summary>
/// 1 基于委托封装解耦,去掉重复代码,完成通用代码
/// 根据逻辑条件筛选数据
/// </summary>
/// <param name="list">列表</param>
/// <param name="where">逻辑条件</param>
/// <returns>筛选结果</returns>
public static List<Student> MyWhere1(this List<Student> list, Func<Student, bool> where)
{
List<Student> newList = new List<Student>();
foreach (var item in list)
{
if (where(item))
{
newList.Add(item);
}
}
return newList;
}
/// <summary>
/// 2 泛型,应对各种数据类型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="where"></param>
/// <returns></returns>
public static List<T> MyWhere2<T>(this List<T> list, Func<T, bool> where)
{
List<T> newList = new List<T>();
foreach (var item in list)
{
if (where(item))
{
newList.Add(item);
}
}
return newList;
}
/// <summary>
/// 3 加迭代器,按需获取
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list"></param>
/// <param name="where"></param>
/// <returns></returns>
public static IEnumerable<T> MyWhere<T>(this IEnumerable<T> list, Func<T, bool> where)
{
foreach (var item in list)
{
if (where(item))
{
yield return item;
}
}
}
}
2 匿名类 var
使用匿名类var,编译器可以根据返回的信息自动退税相应的类型。
//匿名类
var newList = students.Select(c => new
{
c.Age,
c.Name,
NameLength = c.Name.Length
});
foreach (var item in newList)
{
Console.WriteLine($"Name:{item.Name} Age:{item.Age} NameLength:{item.NameLength} ");
}
3 linq常用方法介绍
Where
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var newNumbers = numbers.Where(c => c > 6);
Console.WriteLine("Where:" + string.Join(",", newNumbers));
//输出结果:Where:9,8,7
Select
//Select 得到学生的姓名列表
var nameList1 = students.Select(c => c.Name);
Console.WriteLine("Select:" + string.Join(",", nameList1));
//输出:Select:Oliver,小白,老K,土豆,番茄,小红,黎明,黄昏
Take
//Take 从序列的开头返回指定的数量的连续元素。
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var newNumbers = numbers.Take(2);
Console.WriteLine("Take:" + string.Join(",", newNumbers));
//输出结果:Take:5,4
TakeWhile
//TakeWhile 返回序列中的元素,只要指定的条件为真。
//返回结果:System.Collections.Generic.IEnumerable`1 ,其中包含输入序列中出现测试不再能够通过在元素之前的元素。
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 newNumbers = numbers.TakeWhile(n => n < 6);
Console.WriteLine("TakeWhile:" + string.Join(",", newNumbers));
//输出结果:TakeWhile:5,4,1,3
Skip
//Skip 跳过指定的数量的序列中的元素,然后返回剩余元素。
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var newNumbers = numbers.Skip(5);
Console.WriteLine("Skip:" + string.Join(",", newNumbers));
//输出结果:Skip:8,6,7,2,0
SKipWhere
//SKipWhere 只要指定的条件为 true,然后返回剩余元素,跳过序列中的元素。
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var newNumbers = numbers.SkipWhile(c => c < 6);
Console.WriteLine("SKipWhere:" + string.Join(",", newNumbers));
//输出结果:SKipWhere:9,8,6,7,2,0
OrderBy
//OrderBy 正序。
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var newNumbers = numbers.OrderBy(c => c);
Console.WriteLine("OrderBy:" + string.Join(",", newNumbers));
//输出结果:OrderBy:0,1,2,3,4,5,6,7,8,9
OrderByDescending
//OrderByDescending 倒序。
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
var newNumbers = numbers.OrderByDescending(c => c);
Console.WriteLine("OrderByDescending:" + string.Join(",", newNumbers));
//输出结果:OrderByDescending:9,8,7,6,5,4,3,2,1,0
ThenBy
//ThenBy 执行后续排序以根据某个键按升序对序列的元素。
//如同sql的: select * from student order by age,name;
ThenByDescending
//ThenByDescending 根据某个键将执行后续排序顺序,按降序对序列的元素。
//如同sql的: select * from student order by age,name desc;
GroupBy
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0, 2, 3, 3, 4 };
var newNumbers = numbers.GroupBy(c => c).Select(group =>
string.Format("{0}:{1}", group.Key, group.Count())
);
Console.WriteLine("GroupBy:" + string.Join(",", newNumbers));
//输出结果:GroupBy:5:1,4:2,1:1,3:3,9:1,8:1,6:1,7:1,2:2,0:1
Distinct
//Distinct 通过使用的默认相等比较器对值进行比较从序列返回非重复元素。
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0, 2, 3, 3, 4 };
var newNumbers = numbers.Distinct();
Console.WriteLine("Distinct:" + string.Join(",", newNumbers));
//输出结果:Distinct:5,4,1,3,9,8,6,7,2,0
Min
//Min 返回序列中的最小值 System.Int32 值。
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0, 2, 3, 3, 4 };
var minValue = numbers.Min();
Console.WriteLine("Min:" + minValue);
//输出结果:Min:0
Max
//Min 返回序列中的最大值 System.Int32 值。
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0, 2, 3, 3, 4 };
var maxValue = numbers.Max();
Console.WriteLine("Max:" + maxValue);
//输出结果:Max:9
Average
//Average 计算序列的平均值 System.Int32 值。
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0, 2, 3, 3, 4 };
var avg = numbers.Average();
Console.WriteLine("Avg:" + avg);
//输出结果:Avg:4.07142857142857
Sum
//Sum 计算的一系列总和 System.Int32 值。
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0, 2, 3, 3, 4 };
var sum = numbers.Sum();
Console.WriteLine("Sum:" + sum);
//输出结果:Sum:57
First
//First 计算的一系列总和 System.Int32 值。
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0, 2, 3, 3, 4 };
var number = numbers.First();
Console.WriteLine("First:" + number);
//输出结果:First:5
FirstOrDefault
//FirstOrDefault 返回序列中的第一个元素;如果序列中不包含任何元素,则返回默认值。
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0, 2, 3, 3, 4 };
var number = numbers.Where(c => c == 18).FirstOrDefault();
Console.WriteLine("FirstOrDefault:" + number);
//输出结果:FirstOrDefault:0