浅谈C#中LINQ的延迟执行 c#中延时

浅谈C#中LINQ的延迟执行 c#中延时

编码文章call10242024-12-25 10:35:5924A+A-

自定义扩展方法

为了搞清楚LINQ表达式“延迟”执行的原因,首先我们自己来实现类似Linq中的Where和Select扩展方法。Where方法就是根据条件从集合中筛选出满足条件的元素,并返回一个新的集合;Select方法则是将集合投影为一个新的集合。如下的代码中,我们定义了扩展方法MyWhere和MySelect(类似Linq中的Where和Select),在main方法中调用该它们,就能返回长度大于等于3的字符串的新格式(字符串:长度)的集合。

void Main()
{
    List<string> dataLst = new List<string>() { "小李", "洋小豆", "levy", "列位一分钟", "Hi" };
    var retLst = dataLst.MyWhere(p => p.Length >= 3).MySelect(p => #34;{p}:{p.Length}");
    retLst.Dump();
}

public static class MyExt
{
    public static IEnumerable<string> MyWhere(this IEnumerable<string> dataLst, Func<string, bool> func)
    {
        List<string> retLst = new List<string>();
        foreach (string item in dataLst)
        {
            if (func(item))
            {
                #34;找到符合条件的元素:{item}".Dump();
                retLst.Add(item);
            }
        }
        return retLst;
    }

    public static IEnumerable<string> MySelect(this IEnumerable<string> dataLst, Func<string, string> func)
    {
        List<string> retLst = new List<string>();
        foreach (string item in dataLst)
        {
            retLst.Add(func(item));
        }
        return retLst;
    }
}

运行结果如下图所示:

扩展方法改造

上面我们定义的扩展方法MyWhere和MySelect貌似没什么问题。但是,细想下上面示例有两个问题,第一,每执行一个扩展方法都要创建一个新的集合,这样比较浪费空间;第二,处理一个目标集合却遍历了两次集合,效率低。那么,有没有什么方法可以让我像工厂”流水线“那样来处理一个集合呢?答案是:使用yield return,现将扩展方法改造如下:

public static class MyExt
{
    public static IEnumerable<string> MyWhere(this IEnumerable<string> dataLst, Func<string, bool> func)
    {
        foreach (string item in dataLst)
        {
            if (func(item))
            {
                #34;找到符合条件的元素:{item}".Dump();
                yield return item;
            }
        }
    }

    public static IEnumerable<string> MySelect(this IEnumerable<string> dataLst, Func<string, string> func)
    {
        foreach (string item in dataLst)
        {
                yield return func(item);
        }
    }
}

如上代码所示,我们去除了每次创建的集合retLst,并且是使用了yield return来返回元素,这样就解决了上述的两个问题。

延迟执行的原因

延迟的真正原因其实就是使用了yield return,它使得我们可以像工厂流水线那样来处理一个集合,它返回集合中的一个元素,并移动到下一个元素上,只有在遍历集合或特定操作时才会”启动“这条流水线。现在,我们把main方法改造如下:

void Main()
{
    List<string> dataLst = new List<string>() { "小李", "洋小豆", "levy", "列位一分钟", "Hi" };
    var retLst = dataLst.MyWhere(p => p.Length >= 3).MySelect(p => #34;{p}:{p.Length}");
    "结束".Dump();
    retLst.Dump();
}

再次运行,结果如下图所示:

运行结果竟然是先输出了”结束“?是的,这不就是我们所说的延迟嘛!当我们定义Linq查询表达式时,查询就不会运行。查询会在遍历集合或者在集合上调用Count()、Max()等这样的聚合函数或ToXXX()这样的函数时才会运行。因为我们在"结束"输出语句之后才调用的集合遍历(retLst.Dump()其实内部遍历了集合),所以就先输出了”结束“,然后才执行了Linq表达式的,这就是所谓的延迟执行。

#c##.net##linq##Java#

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4