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※

※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※

posted @ 2025-08-27 21:03  qinway  阅读(6)  评论(0)    收藏  举报