博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
编写高质量代码改善C#程序的157个建议[匿名类型、Lambda、延迟求值和主动求值]...
阅读量:7070 次
发布时间:2019-06-28

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

原文:

前言

  从.NET3.0开始,C#开始一直支持一个新特性:匿名类型。匿名类型由var、赋值运算符和一个非空初始值(或以new开头的初始化项)组成。匿名类型有如下基本特性:

1、既支持简单类型也支持复杂类型。简单类型必须是一个非空初始值,复杂类型则是一个以new开头的初始化项。

2、匿名类型的属性是只读的,没有属性设置器,它一旦倍初始化就不可更改。

3、如果两个匿名类型的属性值相同,那么就任务这两个匿名类型相等。

4、匿名类型可以在循环中用作初始化器。

5、匿名类型支持智能感知。

6、匿名类型也可以拥有方法。  

本文已更新至 。本文主要学习记录以下内容:

  建议26、使用匿名类型储存LINQ查询结果

  建议27、在查询中使用Lambda表达式

  建议28、理解延迟求值和主动求值之间的区别

建议26、使用匿名类型储存LINQ查询结果

  我们直接来看一个简单的实例吧,假如现在有一个公司Company的实体类,然后又有一个人员的Person类,现在需要将Person类中的Name和Company类中的Name进行关联,而形成一个新的类型。

Compay类

public class Company    {        public int ComparyId { get; set; }        public string Name { get; set; }    }

Person类

public class Person    {        public int PersonId { get; set; }        public string Name { get; set; }        public int CompanyId { get; set; }    }

简单初始化数据

List
companyList = new List
() { new Company(){ComparyId=1, Name="MicroSoft"}, new Company(){ComparyId=2, Name="SamSung"} }; List
personList = new List
() { new Person(){ PersonId=1,Name="aehyok",CompanyId=1}, new Person(){ PersonId=2,Name="aehyok",CompanyId=2}, new Person(){ PersonId=3,Name="aehyok",CompanyId=1}, new Person(){ PersonId=4,Name="aehyok",CompanyId=2}, };

下面来看最重要的部分

var personWithCompany = from person in personList                                    join company in companyList                                     on person.CompanyId equals company.ComparyId                                    select new { PersonName = person.Name, CompanyName = company.Name };

其中new之前的代码是Linq关键字,new之后的代码就是匿名类型的初始化项。该匿名类型包含两个属性:PersonName和CompanyName。

foreach(var item in personWithCompany)            {                Console.WriteLine(string.Format("{0}\t:{1}", item.PersonName, item.CompanyName));            }            Console.ReadLine();

调用结果如下所示

建议27、在查询中使用Lambda表达式

 Linq实际上是基于扩展方法和lambda表达式的,理解了这一点就不难理解Linq。任何Linq查询都能通过调用扩展方法的方式来替代。下面我们将建议26中的查询语句进行修改

修改之前

var personWithCompany = from person in personList                                    join company in companyList                                     on person.CompanyId equals company.ComparyId                                    select new { PersonName = person.Name, CompanyName = company.Name };

修改之后

var personWithCompany = from person in personList                                    select new { PersonName = person.Name, CompanyName = person.CompanyId == 1 ? "MicroSoft" : "SamSung" };

当然还有另外一种方式

var personWithCompany = personList.Select(person => new { PersonName = person.Name, CompanyName = person.CompanyId == 1 ? "MicorSoft" : "SamSung" });

针对LINQ设计的扩展方法大多应用了泛型委托。System命名空间定义了泛型委托Action、Func、Predicate。可以这样理解这三个委托:Action用于执行一个操作,所以它没有返回值,Func用于执行一个操作并返回一个值,Predicate用于定义一组条件并判断参数是否符合条件。Select扩展方法接受的就是一个Func委托,而Lambda表达式其实就是一个简介的委托,运算符“=>”左边代表的是方法的参数,右边的是方法体。

下面我们再来举个简单的小例子,调用Where扩展方法,查找出“SamSung”公司的员工

var personWithCompany = personList.Select(person => new { PersonName = person.Name, CompanyName = person.CompanyId == 1 ? "MicorSoft" : "SamSung" });            foreach (var item in personWithCompany.Where(pItem => pItem.CompanyName == "SamSung"))            {                Console.WriteLine(item.PersonName);            }

建议28、理解延迟求值和主动求值之间的区别

 我们先继续看一个简单的小例子:

static void Main(string[] args)        {            List
list = new List
() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; var temp1 = from c in list where c > 5 select c; var temp2 = (from c in list where c > 5 select c).ToList
(); list[0] = 11; Console.Write("temp1:"); foreach (var item in temp1) { Console.Write(item.ToString()); } Console.Write("\ntemp2:"); foreach (var item in temp2) { Console.Write(item.ToString()); } Console.ReadLine(); }

这代码很简单,看执行结果

在延迟求值的情况下,只是定义了一个查询,而且不是立刻执行。对查询结果的访问每次都会遍历原集合。如上文中对于temp1的迭代,在迭代之前,我们修改了list[0]的值,可以看到,修改直接影响了迭代的输出。对查询调用ToList、ToArray等方法,将会使其立即执行,由于对list[0]的修改是在temp2查询之后进行的,所以针对list[0]的修改不会影响到temp2的结果。

在使用Linq to SQL时,延迟求值能够带来显著的性能提升。举个例子:如果定义了两个查询:而且采用延迟求值,CLR会合并两次查询并生成一个最终的查询。

转载地址:http://ylzml.baihongyu.com/

你可能感兴趣的文章
NYOJ 6(贪心)
查看>>
深入学习hbase:表,列族,列标识,版本和cell
查看>>
android中同源策略绕过类漏洞学习笔记
查看>>
MYSQL数据库
查看>>
linux环境搭建seafile客户端自动上传文件
查看>>
10.27 函数
查看>>
MySQL查询缓存
查看>>
【问题总结】问题行
查看>>
这种放法会使div像一张纸一样
查看>>
阿里云环境配置
查看>>
Codeforces 455C
查看>>
PHP请求页面
查看>>
【动态规划】旅行
查看>>
Git小白入门
查看>>
基于 HTML5 的 WebGL 和 VR 技术的 3D 机房数据中心可视化
查看>>
PHP,JAVA,NET 开发比较
查看>>
平方开根 - 牛顿迭代(板子整理)
查看>>
java string字符拼接符"+"的研究
查看>>
Layui表格编辑【不依赖Layui的动态table加载】
查看>>
HDU2087剪花布条(KMP)
查看>>