博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
我学Linq/1
阅读量:5134 次
发布时间:2019-06-13

本文共 4898 字,大约阅读时间需要 16 分钟。

我学Linq

Enumerable Where Select

Linq 读作 link 语言集成查询(Language Integrated Query),让我们可以像操作数据库那样操作内存数据。它有个特点,在使用时执行

如何在使用时获取数据,就要用到一个关键字yield,使用时和return一起出现。

先看个例子

static void Main(string[] args)        {            foreach (var item in GenerateStrings())            {                Console.WriteLine(item.ToString());            }        }        static IEnumerable
GenerateStrings() { for (int i = 0; i < 10; i++) { yield return i.ToString(); } }

在foreach的数据源中,调用这个方法。在输出那设一个断点,单步执行,可以看到,数据源并不是在方法执行完成后再返回到foreach中,而是每调用到下一个数据时,在方法中获得下一个数据。这就是yield return.

这种做法有什么好处?在需要的时候调用,数据只在需要用到的时候调入内存,而不是把整个集合都调入内存,节省存储空间,在这个例子里其实并不能很好的体现好嘛。

static void Main(string[] args)        {            var sequence = GenerateStrings();//==①            sequence = sequence.Where(x => x.Length < 2);//==②    x => x.Length < 2//==⑤            foreach (var item in sequence)//==③            {                Console.WriteLine(item.ToString());//==⑥            }        }        static IEnumerable
GenerateStrings()//==④ { for (int i = 8; i < 100; i++) { yield return i.ToString(); } }

在遇到第①,②句时,并没有进到 GenerateStrings其中,而是遇到foreach时,依次进到GenerateStrings中,取到返回值后,再判断⑤子句,成立后才会输出。

但我在调试的时候明明没有进到GenerateStrings,他就已经有结果了,不懂。

再看一个,我们自己写一个扩展方法,功能同上一个的where子句

public static class MyLinq    {        //一个扩展方法        public static IEnumerable
MyWhere(this IEnumerable
source) { foreach (string item in source) { if (item.Length < 2) yield return item; } } } class Program { static void Main(string[] args) { var sequence = GenerateStrings(); sequence = sequence.Where(x => x.Length < 2); var sequence2 = GenerateStrings(); sequence2 = sequence2.MyWhere(); foreach (var item in sequence) { Console.WriteLine(item.ToString()); } foreach (var item in sequence2) { Console.WriteLine(item.ToString()); } Console.ReadKey(); } static IEnumerable
GenerateStrings() { for (int i = 8; i < 100; i++) { yield return i.ToString(); } } }

输出都是一样的

8
9
8
9

介绍一下第二个foreach的执行过程

遇到sequence2 = sequence2.MyWhere();时是先不执行的
在foreach到的时候才会执行MyWhere
到MyWhere中的foreach后,需要一个数据源
那么就去执行var sequence2 = GenerateStrings()
依次的获取数据,拿到一个8后,判断长度是否小于2,满足,返回8,输出。
9也是一样
到10的时候,判断不小于2
重复获取数据,判断,直到99,没有了,退出。

下面改一下那个扩展方法

public static IEnumerable
MyWhere(this IEnumerable
source,Func
predicate) { foreach (string item in source) { if (predicate(item)) yield return item; } }

还有这里

sequence2 = sequence2.MyWhere(x=>x.Length<2);

这样以后,我们的扩展方法就更加灵活,功能上和C#提供的Where就一样了。后面是一个委托,用来判断条件,返回一个bool值,在if里判断。

再牛逼一点,把我们的MyWhere变成一个泛型方法

public static IEnumerable
MyWhere
(this IEnumerable
source, Func
predicate) { foreach (T item in source) { if (predicate(item)) yield return item; } }

改完这个,主函数里是不用动的,泛型大法好。会玩的你知道下一步怎么玩了么?

static IEnumerable
GenerateIntegers() { for (int i = 8; i < 100; i++) { yield return i; } }

写个返回整数的方法咯。

var sequence3 = GenerateIntegers().MyWhere(x => x % 7 == 0);
这个就可以拿到所有7的倍数啦。
但是要注意到,我们刚才那个泛型方法没有任何错误检查机制,所以…

下面是select

select就比较简单了

var sequence4 = GenerateIntegers().Select(x => x.ToString());
var sequence5 = GenerateIntegers().Select(x =>true);
自己感受一下select后面的lambda表达式

如果,我们来重写一下这个select

public static IEnumerable
MySelect(this IEnumerable
source,Func
selector) { foreach (int item in source) { yield return selector(item); } }

像这样

var sequence4 = GenerateIntegers().MySelect(x => x.ToString());
感受一下,结果是一样的。
那么我们又可以写个泛型扩展方法了

public static IEnumerable
MySelect
(this IEnumerable
source, Func
selector) { foreach (TSource item in source) { yield return selector(item); } }

其实select 有一个重载的版本是可以获取索引的

var sequence6 = GenerateIntegers().Select((x,index)=>new { index, str=x.ToString()+"str" });            foreach (var s in sequence6)            {                Console.WriteLine("{0}=={1}", s.index, s.str);            }

借助一个匿名类型,我们可以同时得到索引和内容。

  • 代码
  • 参考资料

转载于:https://www.cnblogs.com/amvincible/p/5185951.html

你可能感兴趣的文章
Iroha and a Grid AtCoder - 1974(思维水题)
查看>>
gzip
查看>>
转负二进制(个人模版)
查看>>
LintCode-Backpack
查看>>
查询数据库锁
查看>>
[LeetCode] Palindrome Number
查看>>
我对于脚本程序的理解——百度轻应用有感
查看>>
SQL更新某列包含XX的所有值
查看>>
网易味央第二座猪场落户江西 面积超过3300亩
查看>>
面试时被问到的问题
查看>>
spring 事务管理
查看>>
VS2008 去掉msvcr90的依赖
查看>>
当前记录已被另一个用户锁定
查看>>
Bootstrap
查看>>
Node.js 连接 MySQL
查看>>
ACM-ICPC 2018 world final A题 Catch the Plane
查看>>
那些年,那些书
查看>>
面向对象六大基本原则的理解
查看>>
注解小结
查看>>
java代码编译与C/C++代码编译的区别
查看>>