C# Linq源码分析之Take方法

这篇具有很好参考价值的文章主要介绍了C# Linq源码分析之Take方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

概要

Take方法作为IEnumerable的扩展方法,具体对应两个重载方法。本文主要分析第一个接收整数参数的重载方法。

源码解析

Take方法的基本定义

public static System.Collections.Generic.IEnumerable Take (this System.Collections.Generic.IEnumerable source, int count);

基本功能是从序列source中,返回指定个数count的相邻元素。

源码分析

Take.cs

public static IEnumerable<TSource> Take<TSource>(this IEnumerable<TSource> source, int count)
{
   if (source == null)
   {
     ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
   }

   return count <= 0 ?
       Empty<TSource>() :
       TakeIterator<TSource>(source, count);
}

Take方法本身代码很简单, 首先作了一个空序列的检查,如果序列为空,则抛出异常。然后如果count是0,即取前0项相邻元素,等价于什么也不作,直接返回,否则调用TakeIterator方法。

Take.SizeOpt.cs

private static IEnumerable<TSource> TakeIterator<TSource>(IEnumerable<TSource> source, int count)
{
    Debug.Assert(count > 0);

    foreach (TSource element in source)
    {
        yield return element;
        if (--count == 0) break;
    }
}

TakeIterator方法并没有像我们之前分析的Where,Select等方法那样,根据功能,定于很多Iterator的派生类来实现具体的功能,而是使用了yield return的方式。

按照count的个数取出对应的元素,以yield return的方式返回。

下面我们使用相同的代码,定义我们自己的扩展方法take 和takeIterator,通过log来搞清楚yield return方式的实现细节。

 public static IEnumerable<TSource> take<TSource>(this IEnumerable<TSource> source, int count)
{
    Console.WriteLine("take is called !");
    if (source == null)
    {             ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
    }
    return count <= 0 ?
        Empty<TSource>() :
        takeIterator<TSource>(source, count);
}

private static IEnumerable<TSource> takeIterator<TSource>(IEnumerable<TSource> source, int count)
{
    Console.WriteLine("TakeIterator is called !");
    Debug.Assert(count > 0);

    foreach (TSource element in source)
    {
        Console.WriteLine("Enter takeIterator Foreach");
        yield return element;
        Console.WriteLine("Return " + element + " from takeIterator Foreach");
        if (--count == 0) break;
    }
}

Case 1 不通过toList或foreach循环来调用take的返回值。

  static void Main(string[] args)
  {
   	 var list = Enumerable.Range(1,10).take(2);
  }

执行结果如下:

C# Linq源码分析之Take方法,.Net,.Net Core,C#基础,c#,linq,开发语言
我们可以看到takeIterator并未被调用。

Case 2: 通过foreach循环来调用take的返回值

static void Main(string[] args)
  {
   	 var list = Enumerable.Range(1,10).take(2);
   	 foreach (var item in list)
      {
          Console.WriteLine("Enter foreach Main function's  foreach");
          Console.WriteLine("Print " + item + " in Main function");
      }
  }

执行结果如下:

C# Linq源码分析之Take方法,.Net,.Net Core,C#基础,c#,linq,开发语言
从执行结果可以看出:

  1. takeIterator函数只执行一次,但是会生成一个状态机,用于返回take出来的所有数据;
  2. Main函数中的foreach每次的取值,是从状态机中获取数据,即通过yield return的方式获取。

结论

通过定义具体迭代器实现的延迟加载和通过yield return方式实现的延迟加载,本质上没有区别。

但是实现上略有不同,定义迭代器方式实现的Where或Select等方法,如果没有取值操作,它只是将迭代器对象返回,迭代器对象中保存了迭代方式和源数据序列,对应的方法会被调用。通过yield return方式实现的迭代器,如果没有取值操作,yield return所在的方法不会被调用。文章来源地址https://www.toymoban.com/news/detail-641624.html

到了这里,关于C# Linq源码分析之Take方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C# 基础精讲】LINQ 基础

    LINQ(Language Integrated Query)是一项强大的C#语言特性,它使数据查询和操作变得更加简洁、灵活和可读性强。通过使用LINQ,您可以使用类似SQL的语法来查询各种数据源,如集合、数组、数据库等。本文将介绍LINQ的基础概念、常见的LINQ操作和示例,以及如何在C#中利用LINQ进行数

    2024年02月12日
    浏览(31)
  • C#基础--Lambda和LINQ

    在.NetFramewok的不同版本都有不同的样子;在.NetCore下也都是支持的; 1.1 .Netframework1.0/1.1时代 1.2 .NetFramework2.0 匿名方法 增加了一个delegate, 可以访问到除了参数以外的局部变量 1.3 .NetFramework3.0 前期 去掉了delegate,添加了一个= goes to 1.4 .NetFramework3.0 后期 去掉了匿名

    2024年02月17日
    浏览(32)
  • C#基础:利用LINQ进行复杂排序

    请你写出linq对表格排序, CODE=3排前面 ,其余按照 CODE降序 排序,CODE一样再按照 字母升序 排序 ID CODE VALUE A0001 1 A A0002 1 B A0003 1 C A0004 2 D A0005 2 E A0006 2 F A0007 3 G A0008 3 H A0009 3 I A0010 4 J 若再加大难度,ID=A0005的排第一,然后CODE=3排前面,其余按照CODE降序排序,再按照字母升序排

    2024年01月18日
    浏览(28)
  • 【C# 基础精讲】LINQ to Objects查询

    LINQ to Objects是LINQ技术在C#中的一种应用,它专门用于对内存中的对象集合进行查询和操作。通过使用LINQ to Objects,您可以使用统一的语法来查询、过滤、排序、分组等操作各种.NET对象。本文将详细介绍LINQ to Objects的基本概念、常见的操作和示例,以帮助您更好地理解如何在

    2024年02月11日
    浏览(25)
  • 【C# 基础精讲】LINQ to XML查询

    LINQ to XML 是 C# 中用于查询和操作 XML 数据的强大工具。它允许您使用 LINQ 查询语法对 XML 文档进行查询、过滤、投影等操作,从而更加方便地处理 XML 数据。本文将详细介绍 LINQ to XML 的基本概念、常见操作以及示例,帮助您了解如何在 C# 中使用 LINQ to XML 进行 XML 数据的查询和

    2024年02月12日
    浏览(28)
  • C# LINQ常用操作方法——提升你的编程效率

    导语:C# LINQ(Language Integrated Query)是一种强大且灵活的查询语言,可以将数据查询、过滤、排序和转换等操作无缝集成到C#代码中。本文将介绍一些常用的LINQ操作方法,帮助熟练掌握LINQ的使用,并进一步提升编程效率。 对于初学者来说,基本的查询操作是使用LINQ时的关键

    2024年02月06日
    浏览(35)
  • 【C#】【System.Linq】一些便捷的数据处理方法(Range、Select)

    因为用习惯了Python中一些便捷的方法,随即查询C#中有没有类似的。  一、Range()方法 在Python中,range(Start,End,Step)可以直接生成一个可迭代对象,便用于需要循环多次处理某些代码块: (注:Range方法中的End是开区间,range(1,10)实际的取值是(1 ~ 9))   在C#中也

    2024年02月08日
    浏览(35)
  • C# Linq 学会使用,学会自己编写Linq

    Linq我暂时理解为,一种内置的非常方便的数据查询的工具 我们先学习它的使用 //数据类 //新建了一个List数据,用来测试数据查询  //现在定义一个需求,需要查出 id2 的数据 引用Linq的命名空间  引用命名空间之后,我们的list对象,拥有了一个扩展方法,Where (扩展方法,在之前的博客

    2024年02月06日
    浏览(34)
  • EF.Core 使用Linq的Contact联合查询问题

    在.net Core 5 WebAPI 项目中应用 EF Core 5 实体框架,使用Linq的Contact联合进行多表查询。 定义两个子查询语句,查询结果 select 返回的对象结构类型都是一致的。 Linq查询结果集封装对象类: DatingComplaint 实体类映射(Fluent API): 但在执行到 ToListAsync() 代码行查询返回结果时,抛

    2024年02月13日
    浏览(37)
  • C# LINQ,SQL

    C#中的LINQ和SQL都是用于查询数据的工具,但它们有以下异同点: 异同点: 1. LINQ和SQL都可以用于查询数据,但LINQ是在C#中使用的语言集成查询,而SQL是一种独立的查询语言。 2. LINQ和SQL都支持基本的查询操作,如选择、过滤、排序和分组。 3. LINQ和SQL都支持连接多个表,但LI

    2024年02月10日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包