Linq基础必备
1.linq基础必备之对象初始化器和匿名类型因果分析 3.
一:对象初始化器
1.就是在new的时候给公共属性赋值的一种方式
2. 在没有初始化器之前的时候,我们是怎么初始化的呢???
1. 构造函数初始化。。。
public Student(string Name, int Age)
{
this.Name = Name;
this.Age = Age;
}
public Student(string Name):this(Name,default(int))
{
}
2. 一个一个的赋值。。。
var student = new Student();
student.Name = "jack";
student.Age = 20;
3. 为什么要使用初始化器,有一个本质性的原因是什么???【匿名类型】
var person = new { Name = "jack", Age = 20 };
可以看到,其实对象初始化器也是为linq而生。
二:探索匿名类型
1.查看MSIL的中间代码
.class private auto ansi sealed beforefieldinit '<>f__AnonymousType0`2'<'<Name>j__TPar','<Age>j__TPar'>
extends [mscorlib]System.Object
《1》 .class private auto ansi sealed 说明是私有的密封的类。
《2》 '<>f__AnonymousType0`2'<'<Name>j__TPar','<Age>j__TPar'> 类名
《2》 extends [mscorlib]System.Object 可以看到“:”其实就是语法糖,匿名类型都是继承自System.Object
2. 我们看被重写的equals方法是采用逐值比较的模式判断是否相等。
《1》 我们要知道类名的生成大概手段 '<>f__AnonymousType0`2'<'<Name>j__TPar','<Age>j__TPar'>
'<>f__AnonymousType1`3'<'<Name>j__TPar','<Age>j__TPar','<Say>j__TPar'>
《2》 equals采用的是逐值比较
3. 匿名类中的属性是只读的。 IL中只有GET,没有SET。
2.linq基础必备之扩展方法 4.
一:扩展方法
使用 this
《1》 先上代码
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var str = "12345";
var result = str.SayLength();
}
}
public static class Extension
{
public static int SayLength(this string str)
{
return str.Length;
}
}
}
二:如果说“没有扩展方法”,这个世界会是什么样子???
1. 包装类 【在原有的福利上享受新福利】 【不能被继承】的类的扩展
class Program
{
static void Main(string[] args)
{
//var str = "12345";
//var result = str.SayLength();
StrExtenstion str = new StrExtenstion();
str.Str = "12345";
var result = str.SayLength();
}
}
public class StrExtenstion
{
//原有的福利
public string Str { get; set; }
//附加的福利
public int SayLength()
{
return Str.Length;
}
}
如果上面的例子不是很明显,可以看看FCL中的包装类。 List => array
List源码初探
1.
private T[] _items;
public List()
{
this._items = List<T>._emptyArray;
}
2. 继承扩展
FCL中到处都是继承扩展,子类可以享受父类的的福利,并且子类还有独自的附加福利。
继承链太多,导致很难管理和调试。
3. 我既能享受类似继承的语法形式,也能对方法进行扩展。 那这个就是“扩展方法”
三:扩展方法如何定义
1. 静态类 +静态方法
2. 方法的第一个参数叫做“数据源”。也就是扩展方法要依附到谁之上???? 【this string/object str】
3. 扩展方法要注意的地方。
很多专家说,能不用扩展方法就不要用。担心的就是【方法冲突/覆盖】
一定要知道扩展方法是后娘养的,所以说它不如亲生的重要,也就是说不是一等公民。
比如说我在.net 3.5 上定义了一个SayLength方法,如果版本升级到4.0的时候,FCL给string增加了一个SayLength
方法,这时候代码就会出问题,因为我们的扩展SayLength被4.0的SayLength所覆盖,也就导致了bug的产生。
四:linq之扩展方法
linq其实就是在扩展方法上面玩的lambda表达式。
1. linq所玩的扩展方法在哪里???
通过F12,我们发现在System.Linq命名空间之下。
public static TSource Aggregate<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> func);
=>
public static string Aggregate(this IEnumerable source, Func func);
加上泛型之后,就是一个算法的重用。
3.Linq基础必备之yield词法及IEnumerable,GetEnumerator的MSIL分析 5.
一:linq基础必备IEnumerable,IEnumerator
linq查询必须的集合必须要实现这两个接口。
《1》 IEnumerable
GetEnumerator方法
《2》 Current 和MoveNext()属性, Reset方法
二:迭代的基础
1. 因为有了这IEnumerable,IEnumerator接口,我们的集合才可以迭代,可以迭代,我们就可以使用select词法和select扩展方法
2. foreach语法糖
谁知道foreach的MSIL是什么???
《1》 深刻认识foreach这个语法糖
.locals init ([0] class [mscorlib]System.Collections.Generic.List`1<int32> nums,
[1] class [mscorlib]System.Collections.Generic.List`1<int32> V_1,
[2] valuetype [mscorlib]System.Collections.Generic.List`1/Enumerator<int32> V_2,
[3] int32 num)
我们发现,多了一个临时变量,是一个Enumerator<int32>类型变量 V_2
var nums = new List<int>() { 1, 2 };
var MyEnumerator = nums.GetEnumerator();
try
{
while (MyEnumerator.MoveNext())
{
var num = MyEnumerator.Current;
Console.WriteLine(num);
}
}
finally
{
MyEnumerator.Dispose();
}
//foreach (var num in nums)
//{
// Console.WriteLine(num);
//}
三:yield词法探索
了解词法之前,我们需要知道的一个类:Enumerator
这个类其实就是对list进行了一个封装,本质上所谓的movenext和current是对list进行的操作。
yield词法生成的MSIL代码:
.class auto ansi sealed nested private beforefieldinit '<GetNums>d__1'
extends [mscorlib]System.Object
implements class [mscorlib]System.Collections.Generic.IEnumerable`1<int32>,
[mscorlib]System.Collections.IEnumerable,
class [mscorlib]System.Collections.Generic.IEnumerator`1<int32>,
[mscorlib]System.IDisposable,
[mscorlib]System.Collections.IEnumerator
其实 <GetNums>d__1 和 Enumerator 其实就是一样的。
yield词法给我们生成时一个和系统定义的 Enumerator 是具有一样的功能类。
4.linq基础必备之匿名方法,匿名委托,lambda前世今生 6.
一:匿名方法,委托,匿名委托,lambda。。。
1. 委托=> 函数指针
2. 委托不是一个新概念,在其他的编程语言中早已经产生。
javascript:非常熟悉匿名函数【闭包】
C++: 函数指针
3. 那么C#为了引进这个函数指针,将其进行包装成“委托”,同时将非托管的变成托管的。
4. 委托的定义
/// <summary>
/// 这就是一个委托的定义
/// </summary>
/// <param name="str"></param>
delegate void MyAction(string str);
5. 委托的演化过程
函数指针 -> 委托【高等封装】
1. 最初的委托该怎么用???
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyAction action = Run;
Run("mytest");
}
static void Run(string str)
{
Console.WriteLine(str);
}
}
/// <summary>
/// 这就是一个委托的定义
/// </summary>
/// <param name="str"></param>
delegate void MyAction(string str);
}
弊端: 写的代码量过多,在于我还必须要手写一个显示的方法(Run),那有没有好的办法让我不写显式的方法。
2. 匿名委托
那么匿名委托就是在Run方法上面开刀。
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyAction action = delegate(string str)
{
Console.WriteLine(str);
};
}
}
/// <summary>
/// 这就是一个委托的定义
/// </summary>
/// <param name="str"></param>
delegate void MyAction(string str);
}
可以看到,已经成功的把显式方法去掉了,上面就是一个典型的匿名方法,其中有delegate包装了起来,
现在可以动刀的地方就是匿名函数:
MyAction action = delegate(string str)
{
Console.WriteLine(str);
};
有没有这种方法呢??? 有的,那就是lambda表达式。。。。
3.lambda表达式
MyAction action = str => Console.WriteLine(str);
通过对比,发现原来可以向参数声明,大括号,delegate都可以踢掉。。。
我们成功的将代码从 27 优化到了 24行。。。。
4. 还有优化的空间吗???
看了代码之后,惟一可以优化的地方就是delegate声明。
因为FCL中给我们定义了三个系统委托,一个叫做Action,一个叫做Func,一个叫做Predicate。
我们把delegate删掉之后,用了一个系统委托,成功的将代码从24号优化到了18行。
本质上来说,我们将曾今10几行的代码 成功的优化到了1行。
没有编译器的帮忙,绝对不能优化到这样的极致。
5. Action 封装一个方法,该方法只有一个参数并且不返回值。
通过ILSpy可以看到,Action最多接受8个参数。。。
【重点在于无返回值】
6. Func 封装一个不具有参数但却返回 TResult 参数指定的类型值的方法。
【重点再于有返回值】
7.Predicate 入参的类型随意,返回值必须是bool,
从整个演化的过程来看,它就是一个代码优化,代码压缩的过程,并且非常具有优雅性。
Linq基础必备的更多相关文章
- [.net 面向对象编程基础] (19) LINQ基础
[.net 面向对象编程基础] (19) LINQ基础 上两节我们介绍了.net的数组.集合和泛型.我们说到,数组是从以前编程语言延伸过来的一种引用类型,采用事先定义长度分配存储区域的方式.而集合是 ...
- LINQ基础概述
介绍LINQ基础之前,首说一下LINQ 的历史和LINQ是什么,然后说一下学习 LINQ要了解的东西和 LINQ基础语法 LINQ 的历史 从语言方面的进化 –委托 –匿名方法 –Lambda表达 ...
- LINQ基础(二)
本文主要介绍LINQ查询操作符 LINQ查询为最常用的操作符定义了一个声明语法.还有许多查询操作符可用于Enumerable类. 下面的例子需要用到LINQ基础(一)(http://www.cnblo ...
- LINQ基础(三)
一.并行LINQ System.Linq名称空间中包含的类ParallelEnumerable可以分解查询的工作,使其分布在多个线程上. 尽管Enumerable类给IEnumerable<T& ...
- Linq基础操作之Select,Where,OrderBy,ThenBy源码分析
Linq基础操作之Select,Where,OrderBy,ThenBy源码分析 二:Select 它是延迟执行.yield有得一拼,因为他们都是生成了一个枚举类. if (source is TSo ...
- python 之 Django框架(服务器程序和应用程序、基础必备三件套及相关配置)
第十二章 Django框架 12.1 服务器程序和应用程序 服务器程序负责对socket服务器进行封装,并在请求到来时,对请求的各种数据进行整理.应用程序则负责具体的逻辑处理.为了方便应用程序的开发, ...
- 20.C#LINQ基础和简单使用(十一章11.1-11.2)
终于看到了第11章,之前虽然也有看过,但没有太仔细,在工作中也偶尔会使用,但不明白其中的原理,那现在就来讲讲LINQ,做一做书虫~~ 首先先了解下LINQ的三个要点: LINQ不能把非常复杂的查询表达 ...
- LINQ之路(1):LINQ基础
本文将从什么是LINQ(What).为什么使用LINQ(Why)以及如何使用LINQ(How)三个方面来进行说明. 1.什么是LINQ LINQ(Language Integrated Query)是 ...
- Linq基础知识小记四之操作EF
1.EF简介 EF之于Linq,EF是一种包含Linq功能对象关系映射技术.EF对数据库架构和我们查询的类型进行更好的解耦,使用EF,我们查询的对象不再是C#类,而是更高层的抽象:Entity Dat ...
随机推荐
- CentOS7.6安装PM2(Npm方式全局安装)
安装前提: 1. node环境 2. npm 安装开始: 第一步:全局安装,npm install -g pm2 第二步: 保存当前进程状态,pm2 save 第三步: 生成开机自启动服务,pm2 s ...
- qrcode——js生成二维码
1.引入 qrcode.min.js(点击下载demo) 2.html: <div id="qrcode"></div> js: var qrcode = ...
- autofs文件自动挂载系统
为了自己使用方便,利用iso文件制作了自己的rhel6.4的yum源,每次都手动进行mount,十分不便 后来在/etc/rc.local中写入了mount命令,方便多了. 时间一久,发现新的问题出现 ...
- avalon最佳实践
最近从angular的QQ群与新浪微博拉了许多人来用我的avalon,成为第一批登上方舟,脱离DOM苦海的人.短短三个月内,5群的朋友也搞出几个切实实行的案例了.为应对粉丝们高益高涨的热情,遂放出此文 ...
- Python迭代dict的value
我们已经了解了dict对象本身就是可迭代对象,用 for 循环直接迭代 dict,可以每次拿到dict的一个key. 如果我们希望迭代 dict 对象的value,应该怎么做? dict 对象有一个 ...
- 在Ajax请求中什么时候用GET方式什么时候用POST方式?
当我们有大量数据要传送时最好的办法是一次发出多个只传递少量信息的Ajax调用时.如果你正用一个Ajax调用发送大量数据,那么最好是结束这种做法,因为这样做并不能节约时间. 因此,需要传送大量数据能成为 ...
- https 理解
这张图已经很明白,以下为翻译: 一.秘钥传输过程(确认秘钥相同) 1.请求服务端 2.服务端有公司要 3.公钥发给客户端 4.验证发过来的公钥crt,生成随机秘钥,并用此公钥加密 5.加密后的秘钥发给 ...
- Fog
[Fog] Fog parameters are controlled with Fog command. Fogging blends the color of the generated pixe ...
- java中的==、equals()、hashCode()
java中的==.equals().hashCode()源码分析 在java编程或者面试中经常会遇到 == .equals()的比较.自己看了看源码,结合实际的编程总结一下. 1. == java中 ...
- 695. Max Area of Island最大岛屿面积
[抄题]: 求最多的联通的1的数量 Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (repre ...