07-02 C# linq高级实现

25 篇文章 2 订阅

一、接口实现Where扩展

上一章我们最终得到的where扩展方法实现如图,但是还是有缺点:只支持List调用改扩展方法,那么能不能让它更加灵活呢?
在这里插入图片描述
当然可以:可以通过IEnumerable接口来扩展,这样做的好处:

  • 通过接口来扩展,只要实现了这个接口的,都可以使用这个扩展(如List,HashSet等)
  • 扩展性更好,更加通用
/// <summary>
/// 
/// 将原来的List<T>改为IEnumerable<T>
/// 优点是什么?
/// 
///    1、通过接口来扩展,只要实现了这个接口的,都可以使用这个扩展
///    2、扩展性更好,更加通用
///     
/// </summary>
/// <param name="resource"></param>
/// <param name="func"></param>
/// <returns></returns>
public static IEnumerable<T> WhereEnumerable<T>(this IEnumerable<T> resource, Func<T, bool> func) where T : class
{
    var resultList = new List<T>();
    //可以使用for循环遍历,将满足条件的随想添加到resultList集合中
    foreach (var item in resource)
    {
        if (func.Invoke(item))
        {
            resultList.Add(item);
        }
    }
    return resultList;
}

思考:还能优化吗?

二、yield 迭代器关键字

  • yield关键字必须与IEnumerable配合使用,二者密不可分
  • 按需取用:找到一个,取出并用一个,然后再找下一个
/// <summary>
/// 
/// yield关键字必须与IEnumerable<T>配合使用,二者密不可分
/// 
/// 优点是什么?
/// 
///    1、按需取用:找到一个,取出并用一个,然后再找下一个
///     
/// </summary>
/// <param name="resource"></param>
/// <param name="func"></param>
/// <returns></returns>
public static IEnumerable<T> WhereIterator<T>(this IEnumerable<T> resource, Func<T, bool> func) where T : class
{
    foreach (var item in resource)
    {
        Console.WriteLine("***************开始yield*****************");
        if (func.Invoke(item))
        {
            yield return item;
        }
    }
}
对比

我们再循环里都打印一句话,如图:
在这里插入图片描述
调用
在这里插入图片描述
观察结果:

  • WhereEnumerable方法是循环完成之后将结果返回
  • WhereIterator方法是找到一个就直接返回并使用,然后再进入循环查找下一个
    在这里插入图片描述
    二者的代码运行顺序也是不同的:
    (1)WhereEnumerable方法:
    可以看到,点击F10之后,断点立刻进入WhereEnumerable方法中,步骤如下:
  1. 完成所有循环,返回结果
  2. 然后在调用方使用返回结果。

在这里插入图片描述
(2)WhereIterator方法:
可以看到,点击F10之后,断点不是立刻进入WhereIterator方法中,具体步骤如下:

  1. 而是先到返回结果使用的地方
  2. 然后再进入WhereIterator方法中,循环循环,一旦找到第一个匹配结果,立马返回到返回结果使用的地方使用该匹配结果
  3. 然后再次进入WhereIterator寻找匹配的结果(此时直接进入循环中匹配并返回结果,并不会再循行foreach这行代码)

在这里插入图片描述

本质

yield 关键字的本质是一个迭代器状态机,加了yield关键字的方法通过反编译工具反编译之后可以看到:

  • 自动生成了一个泛型类副本
  • 自动在方法上添加了IteratorStateMachine特性,参数是生成的泛型类
    在这里插入图片描述
核心

迭代器状态机的核心要义:只要找到一个符合当前条件的数据,就直接返回。
通过反编译,我们可以在生成的泛型类中找到MoveNext方法,如下在这里插入图片描述
上图可以看到,核心就是通过递归找到符合条件的数据,然后直接返回并使用,而后将状态恢复到原始状态,接着再次寻找下一个符合条件的数据并返回。

三、linq中where的本质

把固定不变的逻辑封装起来,把可变的逻辑封装成委托来传递。

四、本文代码

LinqAdvancedExtension.cs

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值