02020207 .NET Core重难点知识07-为何要学LINQ、Lambda是怎么来的、解密LINQ方法
02020207 .NET Core重难点知识07-为何要学LINQ、Lambda是怎么来的、解密LINQ方法
1. 为何要学LINQ(视频Part2-14)
1.1 LINQ让数据处理变得简单
- 统计一个字符串中每个字母出现的频率(忽略大小写),然后按照从高到低的顺序输出评率高于2次的单词和其出现的评率。
var items = s.Where(c => char.IsLetter(c)) // 过滤非字母
.Select(c => char.ToLower(c)) // 大写字母转换为小写字母
.GroupBy(c => c) // 根据字母进行分组
.Where(g => g.Count() > 2) // 过滤出现次数小于2
.OrderByDescending(g => g.Count()) // 按次数排序
.Select(g => new {Char = g.Key, Count = g.Count()}); //
补充:Python中NumPy可以实现数据处理,这个与LINQ类似。
- LINQ可以让数据处理傻瓜化,即使非常复杂的逻辑也可以用LINQ来应对。LINQ写出来的代码,对计算机性能效率不一定是最高的,在性能可以忍受的范围内使用LINQ是一种简单高效的方法。
1.2 委托 → Lambda → LINQ
- 复习委托
// 委托知识点复习1:委托是可以指向方法的类型,调用委托变量时执行的就是变量指向的方法
using System;
namespace Demo02
{
class Program
{
delegate void D1();
delegate int D2(int i1, int i2);
static void Main(string[] args)
{
D1 d1 = F1;
d1();
d1 = F2;
d1();
D2 d2 = F3;
Console.WriteLine($"{d2(10, 20)}");
Console.ReadLine();
}
static void F1()
{
Console.WriteLine("我是F1");
}
static void F2()
{
Console.WriteLine("我是F1");
}
static int F3(int x, int y)
{
return x + y;
}
}
}
控制台输出:
我是F1
我是F1
30
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// @2 在日常开发中,自己很少定义委托类型。因为在.NET中定义了泛型委托Action(无返回值)和Func(有返回值),所以一般不用自定义委托类型。
using System;
namespace Demo02
{
class Program
{
static void Main(string[] args)
{
Func<int, int, int> f3 = F3; // 有返回值,使用内置的Func,两个参数int,一个返回值int。
Console.WriteLine($"{f3(10, 20)}");
Func<int, int, string> f4 = F4; // 有返回值,使用内置的Func,两个参数int,一个返回值为string。
Console.WriteLine($"{f4(5, 10)}");
Action<int, string> f5 = F5; // 无返回值,使用内置的Action,两个参数。
f5(10, "Qinway");
Console.ReadLine();
}
static int F3(int x, int y)
{
return x + y;
}
static string F4(int i, int j)
{
return "Qinway";
}
static void F5(int i, string s)
{
Console.WriteLine("我是F5");
}
}
}
控制台输出:
30
Qinway
我是F5
1.3 查看对象浏览器
- 对象浏览器:VS 2019 → 视图 → 对象浏览器 → 搜索 → Func → System.Func<int T, out TResult>...等重载的泛型方法。
2. Lambda是怎么来的(视频Part2-15)
2.1 委托可以指向匿名方法
- 委托变量不仅可以指向普通方法,还可以指向匿名方法。
// @1 委托指向匿名方法的写法
using System;
namespace Demo02
{
class Program
{
static void Main(string[] args)
{
Func<int, int, string> f1 = delegate(int i1, int i2)
{
return $"{i1} + {i2} = {i1 + i2}";
};
string s = f1(10, 20);
Console.WriteLine(s);
Action<int, string> f2 = delegate (int i1, string s1)
{
Console.WriteLine($"{i1}, {s1}");
};
f2(10, "Qinway");
Console.ReadLine();
}
}
}
控制台输出:
10 + 20 = 30
10, Qinway
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// @2 匿名方法写成Lambda表达式形式,显式的声明参数类型
using System;
namespace Demo02
{
class Program
{
static void Main(string[] args)
{
Func<int, int, string> f1 = (int i1, int i2) => {
return $"{i1} + {i2} = {i1 + i2}";
};
string s = f1(10, 20);
Console.WriteLine(s);
Action<int, string> f2 = (int i1, string s1) => {
Console.WriteLine($"{i1}, {s1}");
};
f2(10, "Qinway");
Console.ReadLine();
}
}
}
控制台输出:
10 + 20 = 30
10, Qinway
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// @3 匿名方法写成Lambda表达式形式,去掉参数类型,编译器可以推断出来
using System;
namespace Demo02
{
class Program
{
static void Main(string[] args)
{
Func<int, int, string> f1 = (i1, i2) => {
return $"{i1} + {i2} = {i1 + i2}";
};
string s = f1(10, 20);
Console.WriteLine(s);
Action<int, string> f2 = (i1, s1) => {
Console.WriteLine($"{i1}, {s1}");
};
f2(10, "Qinway");
Console.ReadLine();
}
}
}
控制台输出:
10 + 20 = 30
10, Qinway
3. 解密LINQ方法的背后(视频Part2-16)
3.1 使用LINQ方法
- LINQ中提供了很多集合的扩展方法,配合Lambda能简化数据处理。
// 使用LINQ,取出数组中所有大于10的元素。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo02
{
class Program
{
static void Main(string[] args)
{
int[] nums = new int[] { 3, 5, 11, 20, 50, 100 };
IEnumerable<int> result = nums.Where(i => i > 10); // @1 Where是using System.Linq下的扩展方法。
foreach (int item in result)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
}
}
控制台输出:
20
50
100
说明:
1. Where方法会变量集合中每个元素,对每个元素都调用Lambda表达式((i => i > 10),判断是否为true。如果为true,则返回到集合result中。
2. =>左边的i表示数组中的每一个元素
3. =>右边用i > 10进行判断,如果结果为true,当前遍历到的数就会返回到result这个新可迭代对象中。
3.2 自定义LINQ方法
// 形式1,使用自定义方法来实现取出数组中所有大于10的元素,普通写法。
using System;
using System.Collections.Generic;
using System.Linq;
namespace Demo02
{
class Program
{
static void Main(string[] args)
{
int[] nums = new int[] { 3, 5, 11, 20, 50, 100 };
IEnumerable<int> result = MyWhere01(nums, i => i > 10); // 这里没有用扩展方法的调用形式
foreach (int item in result)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
static IEnumerable<int> MyWhere01(IEnumerable<int> items, Func<int, bool> f)
{
List<int> result = new List<int>();
foreach (int it in items)
{
if(f(it) == true)
{
result.Add(it);
}
}
return result;
}
}
}
控制台输出:
20
50
100
说明:此种形式,是创建了一个新数组result,然后将符合条件的元素放到新数组中。方法返回新数组之后,再用foreach遍历result。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 形式2,使用自定义方法来实现取出数组中所有大于10的元素,使用迭代器的写法。
using System;
using System.Collections.Generic;
namespace Demo02
{
class Program
{
static void Main(string[] args)
{
int[] nums = new int[] { 3, 5, 11, 20, 50, 100 };
IEnumerable<int> result = MyWhere02(nums, i => i > 10);
foreach (int item in result)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
static IEnumerable<int> MyWhere02(IEnumerable<int> items, Func<int, bool> f)
{
foreach (int it in items)
{
if (f(it) == true)
{
yield return it;
}
}
}
}
}
控制台输出:
20
50
100
说明:
1. 此种形式,是将MyWhere02方法中符合条件的当前元素直接返回,然后使用Console.WriteLine()打印当前元素,然后回到继续MyWhere02方法判断元素是否符合,如果符合,继续打印当前元素,形成流水式作业。
2. 这样做的好处是数据处理效率更高,因为不用像形式1中将所有数据处理一遍,然后返回。而是处理一个,直接返回,然后处理下一个。这样可以一边获得数据,一遍处理数据,这样效率更高。
3.3 C#中推断类型的注意事项
- 可以使用var让编译器的类型推断来简化类型的声明,这个在LINQ中很常用。
- C#的var和JavaScript的var不一样,仍然是强类型的。
- C#中的弱类型是dynamic。
- var结合匿名类型,在今后开发中用的较多。
// 使用推断类型简化3.2中形式2
using System;
using System.Collections.Generic;
namespace Demo02
{
class Program
{
static void Main(string[] args)
{
var nums = new int[] { 3, 5, 11, 20, 50, 100 }; // 使用推断类型
var result = MyWhere02(nums, i => i > 10); // 使用推断类型
foreach (int item in result)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
static IEnumerable<int> MyWhere02(IEnumerable<int> items, Func<int, bool> f)
{
foreach (int it in items)
{
if (f(it) == true)
{
yield return it;
}
}
}
}
}
控制台输出:
20
50
100
结尾
书籍:ASP.NET Core技术内幕与项目实战
视频:https://www.bilibili.com/video/BV1pK41137He
著:杨中科
ISBN:978-7-115-58657-5
版次:第1版
发行:人民邮电出版社
※敬请购买正版书籍,侵删请联系85863947@qq.com※
※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※

浙公网安备 33010602011771号